TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Error: Debug Failure. False expression.

Open calebpitan opened this issue 2 years ago • 12 comments

Bug Report

🔎 Search Terms

debug failure, false expression, at object.first

🕗 Version & Regression Information

  • This is a crash
  • This is the behavior in every version I tried, 4.9.5, and I reviewed the FAQ for entries about it
  • I was unable to test this on prior versions because I had other issues with prior versions that made me update to a later version

⏯ Playground Link

Playground link with relevant code

💻 Code

stack trace:

/Users/calebpitan/source/work/zendwa/emailing-service/node_modules/typescript/lib/tsc.js:99615
                throw e;
                ^

Error: Debug Failure. False expression.
    at Object.first (/Users/calebpitan/source/work/zendwa/emailing-service/node_modules/typescript/lib/tsc.js:990:18)
    at getSpecifierForModuleSymbol (/Users/calebpitan/source/work/zendwa/emailing-service/node_modules/typescript/lib/tsc.js:45313:36)
    at serializeAsAlias (/Users/calebpitan/source/work/zendwa/emailing-service/node_modules/typescript/lib/tsc.js:46419:107)
    at serializeSymbolWorker (/Users/calebpitan/source/work/zendwa/emailing-service/node_modules/typescript/lib/tsc.js:46084:25)
    at serializeSymbol (/Users/calebpitan/source/work/zendwa/emailing-service/node_modules/typescript/lib/tsc.js:45978:25)
    at /Users/calebpitan/source/work/zendwa/emailing-service/node_modules/typescript/lib/tsc.js:45963:29
    at Map.forEach (<anonymous>)
    at visitSymbolTable (/Users/calebpitan/source/work/zendwa/emailing-service/node_modules/typescript/lib/tsc.js:45962:81)
    at symbolTableToDeclarationStatements (/Users/calebpitan/source/work/zendwa/emailing-service/node_modules/typescript/lib/tsc.js:45847:17)
    at /Users/calebpitan/source/work/zendwa/emailing-service/node_modules/typescript/lib/tsc.js:44127:106

Node.js v18.11.0

source: node_modules/typescript/lib/tsc.js

ts.firstOrUndefined = firstOrUndefined;
first(array) {
    ts.Debug.assert(array.length !== 0);
    return array[0];
}
ts.first = first;

tsconfig.json:

{
  "compilerOptions": {
    "module": "ES2020",
    "moduleResolution": "node",
    "allowJs": true,
    "checkJs": false,
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "target": "ES2022",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "rootDir": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strict": true,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "noImplicitThis": true,
    "strictBindCallApply": true,
    "alwaysStrict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "paths": {
      "@/shared/*": ["backend-services-shared/src/*"], // contains .js files
      "@/utils/*": ["src/utils/*"],
      "@/modules/*": ["src/modules/*"]
    }
  },
  "exclude": ["node_modules", "test", "dist"]
}

🙁 Actual behavior

Error happens when I turn on allowJs

🙂 Expected behavior

allowJs shouldn't crash build process and should include the js files from the source in the build output 😔

calebpitan avatar Feb 24 '23 16:02 calebpitan

We'd need a way to reproduce the problem. Do you have a repo we can clone, or other way to produce this crash?

RyanCavanaugh avatar Feb 24 '23 16:02 RyanCavanaugh

To help narrow it down, you might be able to modify your tsc.js at /Users/calebpitan/source/work/zendwa/emailing-service/node_modules/typescript/lib/tsc.js

                  symbolTableToDeclarationStatements: function (symbolTable, enclosingDeclaration, flags, tracker, bundled) {
+                     console.log("FILE NAME", ts.getSourceFileOfNode(enclosingDeclaration).fileName);
                      return withContext(enclosingDeclaration, flags, tracker, function (context) { return symbolTableToDeclarationStatements(symbolTable, context, bundled); });
                  },

It starts at line 44125 in TypeScript 4.9.5's tsc.js.

DanielRosenwasser avatar Feb 24 '23 20:02 DanielRosenwasser

Thanks to @DanielRosenwasser "debug snippet" which seems to have pointed me in the right direction, and did help narrow it down just as he mentioned. I inserted a console statement on that line and it was able to log the filenames till it crashed again. I inspected the last logged file before crash and found out it imported files that imported uninstalled modules/deps.

Instaliing the missing module fixed it and tsc could build successfully.

But this doesn't mean there's no problem. The problem is: the compiler couldn't resolve a specifier, why couldn't it just say so in an understandable, helpful error message, rather than an elusive jargon like "Error: Debug Failure. False expression."?

first(array) {
    ts.Debug.assert(array.length !== 0);
    return array[0];
}

It seems, apparently, the only thing that makes this array empty is an unresolved module specifier, if so, the Debug.assert could make room for a custom error message rather than a generic "Debug Failure. False expression"

calebpitan avatar Feb 25 '23 05:02 calebpitan

But this doesn't mean there's no problem. The problem is: the compiler couldn't resolve a specifier, why couldn't it just say so in an understandable, helpful error message, rather than an elusive jargon like "Error: Debug Failure. False expression."?

The message is cryptic because it's intended for TS developers, not end-users. A debug assert being hit means the compiler has done something that, if it were functioning correctly, would literally never happen (in this case calling first() with an empty array); it always indicates a bug that has to be fixed elsewhere. In this case, it sounds like there might be a missing check during module specifier resolution.

In other words: "Debug Failure" is a crash, not an expected error condition.

fatcerberus avatar Feb 25 '23 06:02 fatcerberus

I got this same error.

Specifically, it seems like I had @types/gopd installed, and then also made a types/gopd/index.d.ts, in which I provided my own definition that uses export =. @RyanCavanaugh can you reproduce it with that approach?

Note that it does not crash when my overload uses export default, but every CJS module's type is export = so I need to use that.

ljharb avatar Feb 27 '23 20:02 ljharb

I tried briefly, but haven't gotten far. Can you do the same thing I told @calebpitan to try above and see if you can provide a pared down version of that file? A pared-down config file is going to be helpful too.

DanielRosenwasser avatar Feb 27 '23 20:02 DanielRosenwasser

@DanielRosenwasser when i apply that console log diff (which is slightly tricker in TS 5 beta), it's never hit - the line it dies on is Debug.assert(node.kind !== 257 /* VariableDeclaration */); inside checkAliasSymbol, and when i add a console.log(node) in front of it, i get:

<ref *2> Node4 {
  pos: 64,
  end: 88,
  kind: 257,
  id: 0,
  flags: 262144,
  modifierFlagsCache: 536875008,
  transformFlags: 0,
  parent: <ref *1> Node4 {
    pos: 59,
    end: 88,
    kind: 258,
    id: 0,
    flags: 262144,
    modifierFlagsCache: 536875008,
    transformFlags: 4194304,
    parent: Node4 {
      pos: 59,
      end: 89,
      kind: 240,
      id: 0,
      flags: 262144,
      modifierFlagsCache: 536875008,
      transformFlags: 4194304,
      parent: [Node4],
      original: undefined,
      emitNode: undefined,
      modifiers: undefined,
      declarationList: [Circular *1],
      jsDoc: undefined,
      flowNode: [Object]
    },
    original: undefined,
    emitNode: undefined,
    declarations: [
      [Circular *2],
      pos: 64,
      end: 88,
      hasTrailingComma: false,
      transformFlags: 0
    ]
  },
  original: undefined,
  emitNode: undefined,
  symbol: Symbol4 {
    flags: 2097152,
    escapedName: '$gOPD',
    declarations: [ [Circular *2] ],
    valueDeclaration: undefined,
    id: 24904,
    mergeId: 0,
    parent: undefined,
    members: undefined,
    exports: undefined,
    exportSymbol: undefined,
    constEnumOnlyModule: undefined,
    isReferenced: undefined,
    isAssigned: undefined,
    links: undefined
  },
  localSymbol: undefined,
  name: Identifier2 {
    pos: 64,
    end: 70,
    kind: 79,
    id: 0,
    flags: 262144,
    transformFlags: 0,
    parent: [Circular *2],
    original: undefined,
    emitNode: undefined,
    escapedText: '$gOPD',
    jsDoc: undefined,
    flowNode: { flags: 2064, antecedent: [Object], node: [Node4] },
    symbol: undefined
  },
  exclamationToken: undefined,
  type: undefined,
  initializer: <ref *3> Node4 {
    pos: 72,
    end: 88,
    kind: 210,
    id: 0,
    flags: 262144,
    modifierFlagsCache: 0,
    transformFlags: 0,
    parent: [Circular *2],
    original: undefined,
    emitNode: undefined,
    symbol: undefined,
    localSymbol: undefined,
    expression: Identifier2 {
      pos: 72,
      end: 80,
      kind: 79,
      id: 0,
      flags: 262144,
      transformFlags: 0,
      parent: [Circular *3],
      original: undefined,
      emitNode: undefined,
      escapedText: 'require',
      jsDoc: undefined,
      flowNode: [Object],
      symbol: undefined
    },
    questionDotToken: undefined,
    typeArguments: undefined,
    arguments: [
      [Node4],
      pos: 81,
      end: 87,
      hasTrailingComma: false,
      transformFlags: 0
    ]
  },
  jsDoc: [ jsDocCache: [] ]
}

Happy to debug live elsewhere, or with comments here, since it's consistently reproducible for me - just not in a branch i'm ready to share publicly.

Config file:

{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file */

    /* Language and Environment */
    "target": "es2022",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
    "useDefineForClassFields": true,                     /* Emit ECMAScript-standard-compliant class fields. */

    /* Modules */
    "module": "commonjs",                                /* Specify what module code is generated. */
    // "rootDir": "./",                                  /* Specify the root folder within your source files. */
    // "moduleResolution": "node",                       /* Specify how TypeScript looks up a file from a given module specifier. */
    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
    "typeRoots": ["types", "@node_modules/@types"],                                  /* Specify multiple folders that act like `./node_modules/@types`. */
    // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
    // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
    // "resolveJsonModule": true,                        /* Enable importing .json files */
    // "noResolve": true,                                /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */

    /* JavaScript Support */
    "allowJs": true,                                  /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
    "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
    // "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */

    /* Emit */
    "noEmit": true,                                   /* Disable emitting files from a compilation. */

    /* Interop Constraints */
    "allowSyntheticDefaultImports": true,                /* Allow 'import x from y' when a module doesn't have a default export. */
    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */

    /* Type Checking */
    "strict": true,                                      /* Enable all strict type-checking options. */
    "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied `any` type.. */
    "strictNullChecks": true,                         /* When type checking, take into account `null` and `undefined`. */
    "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
    "strictBindCallApply": true,                      /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
    "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
    "noImplicitThis": true,                           /* Enable error reporting when `this` is given the type `any`. */
    "useUnknownInCatchVariables": true,               /* Type catch clause variables as 'unknown' instead of 'any'. */
    "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
    "noUnusedLocals": true,                           /* Enable error reporting when a local variables aren't read. */
    "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read */
    "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
    "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
    "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
    "noUncheckedIndexedAccess": true,                 /* Include 'undefined' in index signature results */
    "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
    "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type */

    /* Completeness */
    // "skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
  },
  "include": [
    "**/*.js"
  ],
  "exclude": [
    "coverage/**"
  ],
}

ljharb avatar Feb 27 '23 21:02 ljharb

That seems like a separate stack trace then, right? If so, what is the stack trace? And can you switch the console.log(node) to console.log("FILE NAME", ts.getSourceFileOfNode(enclosingDeclaration).fileName);?

DanielRosenwasser avatar Feb 27 '23 21:02 DanielRosenwasser

I can't, because ts is not defined in that function.

Stack trace:

$PWD/node_modules/typescript/lib/tsc.js:113967
      throw e;
      ^

Error: Debug Failure. False expression.
    at checkAliasSymbol ($PWD/node_modules/typescript/lib/tsc.js:78641:17)
    at checkVariableLikeDeclaration ($PWD/node_modules/typescript/lib/tsc.js:76204:7)
    at checkVariableDeclaration (/$PWD/node_modules/typescript/lib/tsc.js:76287:5)
    at checkSourceElementWorker ($PWD/node_modules/typescript/lib/tsc.js:79258:16)
    at checkSourceElement ($PWD/node_modules/typescript/lib/tsc.js:79089:7)
    at forEach ($PWD/node_modules/typescript/lib/tsc.js:37:22)
    at checkVariableStatement ($PWD/node_modules/typescript/lib/tsc.js:76297:5)
    at checkSourceElementWorker ($PWD/node_modules/typescript/lib/tsc.js:79227:16)
    at checkSourceElement ($PWD/node_modules/typescript/lib/tsc.js:79089:7)
    at forEach ($PWD/node_modules/typescript/lib/tsc.js:37:22)

Node.js v19.6.1

ljharb avatar Feb 27 '23 21:02 ljharb

@DanielRosenwasser actually turns out i was authoring my "declare module" incorrectly - i was doing type x = whatever instead of function x, and the export = with the type was what was crashing. Hope that helps :-)

ljharb avatar Feb 27 '23 23:02 ljharb

This is happening to me on version 5.3.3 of TypeScript.

image

I'm going to try 5.4.5 to see if this is resolved.

divmgl avatar May 01 '24 22:05 divmgl

@divmgl that seems like an unrelated stack trace. Feel free to open a separate issue if you can provide a repro on the latest version of TS.

DanielRosenwasser avatar May 02 '24 00:05 DanielRosenwasser

I'm getting this too after updating from 5.2.2 to 5.6.2. Similar to others reporting this, I have allowJs: true set.

zigcccc avatar Sep 13 '24 11:09 zigcccc

@zigcccc could you prepare a repro case of the problem? you could try to remove as much lines from your project as possible (gradually) and bisect the problem this way to the minimal repro case

Andarist avatar Sep 19 '24 09:09 Andarist