Skip to content

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

Closed

Description

@tomdev10

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...?

Activity

  1. AlCalzone commented on Oct 8, 2021

    @AlCalzone
    Contributor

    This looks like a typescript crash

  2. andrewbranch commented on Oct 8, 2021

    @andrewbranch
    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?

  3. tomdev10 commented on Oct 11, 2021

    @tomdev10
    Author

    Hi Andrew Branch (@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?

  4. andrewbranch commented on Oct 11, 2021

    @andrewbranch
    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.

  5. tomdev10 commented on Oct 11, 2021

    @tomdev10
    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?

  6. andrewbranch commented on Oct 11, 2021

    @andrewbranch
    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.

  7. val1984 commented on Nov 2, 2021

    @val1984

    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.

  8. tomdev10 commented on Nov 2, 2021

    @tomdev10
    Author

    Hi Valentin (@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 Andrew Branch (@andrewbranch)

  9. andrewbranch commented on Nov 2, 2021

    @andrewbranch
    Member

    Valentin (@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?

  10. val1984 commented on Nov 3, 2021

    @val1984

    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.

  11. andrewbranch commented on Nov 3, 2021

    @andrewbranch
    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. Valentin (@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.

  12. andrewbranch commented on Nov 3, 2021

    @andrewbranch
    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.

  13. val1984 commented on Nov 15, 2021

    @val1984

    Hey Andrew Branch (@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

  14. andrewbranch commented on Nov 15, 2021

    @andrewbranch
    Member

    Valentin (@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?

  15. val1984 commented on Nov 15, 2021

    @val1984

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

    Correct ✔

  16. andrewbranch commented on Nov 15, 2021

    @andrewbranch
    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.)

  17. val1984 commented on Nov 16, 2021

    @val1984

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

  18. andrewbranch commented on Nov 16, 2021

    @andrewbranch
    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?

  19. val1984 commented on Nov 18, 2021

    @val1984

    Andrew Branch (@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.

  20. andrewbranch commented on Nov 19, 2021

    @andrewbranch
    Member

    Valentin (@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.

  21. fmacherey commented on Jan 4, 2022

    @fmacherey

    Hey Andrew Branch (@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.

  22. fmacherey commented on Jan 4, 2022

    @fmacherey

    Hey Andrew Branch (@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 Valentin (@val1984) can approve, if he has similar code which leads to this error.

    Best, Florian

  23. andrewbranch commented on Jan 4, 2022

    @andrewbranch
    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.

  24. fmacherey commented on Jan 6, 2022

    @fmacherey

    Andrew Branch (@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.

  25. andrewbranch commented on Jan 6, 2022

    @andrewbranch
    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

  26. dgattey commented on Jan 19, 2022

    @dgattey

    Andrew Branch (@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.

  27. andrewbranch commented on Jan 19, 2022

    @andrewbranch
    Member

    Thanks Dylan Gattey (@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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs More InfoThe issue still hasn't been fully clarified

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions