Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strange output from tsc noEmit - unclear where error stems from within app, #46277

Closed
tomdev10 opened this issue Oct 8, 2021 · 27 comments · Fixed by #47604
Closed

Strange output from tsc noEmit - unclear where error stems from within app, #46277

tomdev10 opened this issue Oct 8, 2021 · 27 comments · Fixed by #47604
Labels
Needs More Info The issue still hasn't been fully clarified

Comments

@tomdev10
Copy link

tomdev10 commented Oct 8, 2021

Bug Report

Hi all. Relatively new to TypeScript, but just trying to understand this output from tsc but I can't seem to get to the bottom of it. Please see terminal output below after running tsc command - appears error is in library code, rather than in app - but I'd expect a stack trace or similar to find the type error, but in fact there doesn't seem to be one?

Typescript tools in VSCode show no error in any files - does anyone have any idea what is causing this?

🔎 Search Terms

JSON errors, noEmit, tsc type check, version info, circular structure, "parent", "statements"

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about tsc output with noEmit
  • Tested on 4.4.3 and typescript@next

💻 Code

> tsc --noEmit

/frontend/node_modules/typescript/lib/tsc.js:88155
        return JSON.stringify(buildInfo);
                    ^

TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Node'
    |     property 'statements' -> object with constructor 'Array'
    |     index 0 -> object with constructor 'Node'
    --- property 'parent' closes the circle
    at JSON.stringify (<anonymous>)
    at getBuildInfoText (/frontend/node_modules/typescript/lib/tsc.js:88155:21)
    at emitBuildInfo (/frontend/node_modules/typescript/lib/tsc.js:87960:67)
    at emitSourceFileOrBundle (/frontend/node_modules/typescript/lib/tsc.js:87926:13)
    at forEachEmittedFile (/frontend/node_modules/typescript/lib/tsc.js:87685:28)
    at Object.emitFiles (/frontend/node_modules/typescript/lib/tsc.js:87900:9)
    at Object.emitBuildInfo (/frontend/node_modules/typescript/lib/tsc.js:94075:33)
    at Object.emitBuildInfo (/frontend/node_modules/typescript/lib/tsc.js:96965:67)
    at Object.handleNoEmitOptions (/frontend/node_modules/typescript/lib/tsc.js:95814:25)
    at Object.emit (/frontend/node_modules/typescript/lib/tsc.js:97015:29)

🙁 Actual behavior

This should produce output showing where the error is, rather than displaying either this global error, or something is wrong in the library.

🙂 Expected behavior

I'd expect more detailed info, but I might be wrong...?

@AlCalzone
Copy link
Contributor

This looks like a typescript crash

@andrewbranch andrewbranch added the Needs More Info The issue still hasn't been fully clarified label Oct 8, 2021
@andrewbranch
Copy link
Member

@tomdev10 it's not telling you that you have an error, it's tripping over itself and crashing in a way that it should never do. Can you provide a repo where this happens?

@tomdev10
Copy link
Author

Hi @andrewbranch @AlCalzone - thanks for the speedy reply. I can try and produce a repo, but will take me a bit of time as the content is sensitive so will need to try and remove that.

I know it might be like asking a million dollar quesiton, but any idea what might be causing it? I was wondering if it was clashing typescript versions within the deps somehow?

@andrewbranch
Copy link
Member

From the stack, we can tell that what’s happening is that a parse tree node is ending up in the data that we are attempting to serialize into a .tsbuildinfo file. But that should never happen, and finding out why it’s happening is likely to be very very difficult without a debuggable repro, and probably very easy with one.

@tomdev10
Copy link
Author

Okay fair comment, that makes sense. I will do my best to get one up and running - thanks! Will try and get it done this week.

Inidentally, trying to figure this out myself I came across extendedDiagnostics and this showing that all the node_modules are being type chcked, wondering if this might be why? Or if there is any useful output avaliable from this aid where to look?

@andrewbranch
Copy link
Member

No, --extendedDiagnostics probably won’t tell you much. There’s no rational explanation you can conjure for why this is happening because it’s just a bug, probably caused by a silly mistake somewhere.

@val1984
Copy link

val1984 commented Nov 2, 2021

Hey,
I'm experiencing the same issue, using typescript@4.4.4, called by fork-ts-checker-webpack-plugin@6.4.0. I've narrowed down the issue to being caused by using reselect@4.1.1 in our case. Versions 4.0.0 and 4.1.0 do not cause this issue.
Hope it will help reproducing this issue as I can't share my employer's code either.

@tomdev10
Copy link
Author

tomdev10 commented Nov 2, 2021

Hi @val1984 + et al. I never actually traced this, or got to the bottom of what caused it.

However, I did solve it within my repo, by removing all package-lock.json files (it was a monorepo) and regenerating those. Some contributing to the repo had been runnning npm audit fix --force and this was causing dependancies to update in an uncontrolled fashion.

After this, it worked.

You've done a better job tracing than I have so far, so I'll leave the issue open

FYI @andrewbranch

@andrewbranch
Copy link
Member

@val1984 that’s a pretty good start. Did the problem not reproduce with tsc, or do you just not normally use tsc as part of your workflow?

@val1984
Copy link

val1984 commented Nov 3, 2021

tsc does not exhibit the issue with:

"compilerOptions": {
  "incremental": false,
  "noEmit": true,
  "pretty": true
}

But it does result in the same error as soon as incremental is set to true.

I'm able to run my project when disabling incremental mode (and I have type errors on my project because reselect@4.1.0 included some breaking changes). I'll fix them and let you know if this solves the crashing issue with incremental mode.

@andrewbranch
Copy link
Member

I can't reproduce this just by installing reselect@4.1.1, importing it, and compiling with incremental, but it feels like we're so close. The compiler shouldn't crash like this under any circumstance, so the best thing would be to get a minimal repro that does crash so I can investigate what's going wrong. @val1984 if you're able to extract that, it would be incredibly helpful. I could also probably send you a custom build that logs out everything it’s trying to serialize into build info and maybe that would narrow it down 🤔

Barring all that, I think we’ll just have to let this issue sit and see if someone comes up with a shareable repro.

@andrewbranch
Copy link
Member

I could also probably send you a custom build that logs out everything it’s trying to serialize

Actually let me go ahead and do this so you can try it before you get into a state where it doesn’t repro anymore. Here is a copy of tsc.js from typescript@4.4.4 with the line added at 86695:

console.log(require("util").inspect(buildInfo, { depth: 32 }));

If you have time to try it, you’ll need to download it and drop it into ./node_modules/typescript/lib/ so it can find the lib.d.ts files in the same folder. Then run tsc as normal, and it will spit out a huge blob of JSON-esque output. That blob is not supposed to contain any actual source code, but the crash indicates that it might—feel free to sanitize the output before sharing it; the overall structure should give me a clue as to what’s happening.

@val1984
Copy link

val1984 commented Nov 15, 2021

Hey @andrewbranch,
Sorry for the long delay in replying. My project has about 100k loc and it seems that parts of the output are cut with:
... xxx more items
Is it enough data for you to investigate? Otherwise, what should I do to get you the data you asked?
Thank you very much!
debug.log

@andrewbranch
Copy link
Member

@val1984 nothing in that log looks like a problem, so maybe it did truncate the relevant parts... just to confirm, did it crash with TypeError: Converting circular structure to JSON right after that output?

@val1984
Copy link

val1984 commented Nov 15, 2021

just to confirm, did it crash with TypeError: Converting circular structure to JSON right after that output?

Correct ✔

@andrewbranch
Copy link
Member

Ok, let’s try this

function getBuildInfoText(buildInfo) {
    try {
        return JSON.stringify(buildInfo);
    }
    catch (err) {
        console.log(require("util").inspect(buildInfo, { depth: 32, maxArrayLength: Infinity }));
        throw err;
    }
}

Can you replace getBuildInfoText in tsc.js with this? This will only log during calls that are going to crash, and will not truncate any arrays. (The output will be a lot bigger so I would suggest piping the CLI output to a file directly if you weren’t already doing that. I always forget I should do that until I’m trying to copy and paste something very unwieldy.)

@val1984
Copy link

val1984 commented Nov 16, 2021

@andrewbranch The file weighs 134MB, any idea how to transmit it to you? Or maybe I can filter out most data?

@andrewbranch
Copy link
Member

You can email it to me if you want—${myFirstName}.${myLastName}@microsoft.com. Or you could upload to Dropbox or OneDrive or Google Drive and send me a link?

@val1984
Copy link

val1984 commented Nov 18, 2021

@andrewbranch Sorry, I'm not yet able to share the log with you.
On another note, upgrading to reselect@4.1.4 solved the issue (coincidentally, it includes many changes to the provided Typescript types).
And typescript@4.5.2 still crashes with reselect@4.1.2.

@andrewbranch
Copy link
Member

@val1984 feel free to redact any source file text from the log that makes it a problem to share. What I need to do with it is figure out the path from the top level of that object to the Node object, which shouldn’t be in there. I’m guessing when you look at it, you see a huge repeating cycle. I just need to trace that cycle to the top.

@fmacherey
Copy link

Hey @andrewbranch ,

we are also experiencing this build crash. Our log with your code snippet from 15 Nov 2021 is 128MB big with more than 170k lines.

We have a NextJS application with formerly Preact working fine as intended. We are now willing to switch back to React, and now this error occurs during build. I also tried some older versions of typescript@4.* and the current nightly (2nd January) but with no luck.

I might can send you the log via email, but I need to talk to team members before.

@fmacherey
Copy link

Hey @andrewbranch,

we figured out what the problem is. We had a component, which was included with dyanmic-Import from NextJS. In the imported Component we had a type children: Array<React.ReactChild>; which was false for our case, only single items could appear here.

When we resolved the dynamic import to a normal import, we get the correct message from typescript TS2745: This JSX tag's 'children' prop expects type 'ReactChild[] & ReactNode' which requires multiple children, but only a single child was provided.
Maybe @val1984 can approve, if he has similar code which leads to this error.

Best, Florian

@andrewbranch
Copy link
Member

@fmacherey I’m glad you found a workaround, but you didn’t find “the problem” per se. The problem is and will forever remain a mystery until someone can send me that gigantic log file.

@fmacherey
Copy link

@andrewbranch just to clarify, I used the normal import for debugging, but switched back to dynamic after fixing the types. I think typescript has problems with next' dyamic import to correctly resovle the types.

@andrewbranch
Copy link
Member

This really has nothing to do with imports, resolving types, Next.js, incorrectly supplying an array where a single child should go, or any particular piece of end-user code. There is a very strange bug with serializing complex state during incremental builds, and you’ve happened to find a lever on one end of a Rube Goldberg machine that toggles the problem from a mile away. What’s happening between between that lever and the real problem is not inferable by a human. All I can tell you is that the lever itself is not relevant on its own, or attached to any other machine except the precise one made by your program, and the only way we can understand what’s happening is by observing the whole machine. I have tried to encode clues about its operation in the log file generated by the patched TS version I made, but I’ve yet to see one of these logs ☹️.

Rube Goldberg machine as a TypeScript program

@dgattey
Copy link

dgattey commented Jan 19, 2022

@andrewbranch I just hit this in a similar setup. I'm using Next.js with Yarn PnP. I was also messing with children in some component I was editing, and restricting the types of children that could be passed.

Here's a link to the output of running tsc with a replaced buildInfo . It's happening on this branch of my personal website repo if you want to explore source code! Thanks!

This is what happens without the logs:

/Users/dgattey/checkouts/dg/.yarn/cache/typescript-patch-0b90225f97-2e488dde7d.zip/node_modules/typescript/lib/tsc.js:88443
        return JSON.stringify(buildInfo);
                    ^

TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Node'
    |     property 'statements' -> object with constructor 'Array'
    |     index 0 -> object with constructor 'Node'
    --- property 'parent' closes the circle
    at JSON.stringify (<anonymous>)
    at getBuildInfoText (/Users/dgattey/checkouts/dg/.yarn/cache/typescript-patch-0b90225f97-2e488dde7d.zip/node_modules/typescript/lib/tsc.js:88443:21)
    at emitBuildInfo (/Users/dgattey/checkouts/dg/.yarn/cache/typescript-patch-0b90225f97-2e488dde7d.zip/node_modules/typescript/lib/tsc.js:88248:67)
    at ...

EDIT: yea as suspected, it's from ./src/components/homepage/ColorSchemeToggleCard.tsx because This JSX tag's 'children' prop expects a single child of type 'Children', but multiple children were provided. The type Children there is from ./src/components/ContentCard.tsx and it's just a union of ReactElement, null, and undefined.

This wasn't an error I was seeing live in VSCode until I cleared my yarn cache and reinstalled all yarn packages... but I'm going to chalk that up to Yarn PnP being buggy. I'll leave https://github.com/dgattey/dg/tree/andrew/debugging for you to debug and test in this state.

@andrewbranch
Copy link
Member

Thanks @dgattey—as I suspected, that file shows me exactly what the problem is 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs More Info The issue still hasn't been fully clarified
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants
@dgattey @andrewbranch @val1984 @AlCalzone @tomdev10 @fmacherey and others