{"record":{"id":"4df02b6a6420ad0d","repo":"swc-project/swc","slug":"failed-to-parse-the-value-of-bigintliteral","errorCode":null,"errorMessage":"failed to parse the value of BigIntLiteral","messagePattern":"failed to parse the value of BigIntLiteral","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_estree_compat/src/swcify/lit.rs","lineNumber":145,"sourceCode":"            span: ctx.span(&self.base),\n            tail: self.tail,\n            cooked: self.value.cooked,\n            raw: self.value.raw,\n        }\n    }\n}\n\nimpl Swcify for BigIntLiteral {\n    type Output = BigInt;\n\n    fn swcify(self, ctx: &Context) -> Self::Output {\n        BigInt {\n            span: ctx.span(&self.base),\n            value: self\n                .value\n                .parse()\n                .map(Box::new)\n                .expect(\"failed to parse the value of BigIntLiteral\"),\n            // TODO improve me\n            raw: None,\n        }\n    }\n}\n\nimpl Swcify for DecimalLiteral {\n    type Output = Number;\n\n    fn swcify(self, ctx: &Context) -> Self::Output {\n        Number {\n            span: ctx.span(&self.base),\n            value: self\n                .value\n                .parse()\n                .expect(\"failed to parse the value of DecimalLiteral\"),\n            // TODO improve me\n            raw: None,","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_estree_compat/src/swcify/lit.rs#L127-L163","documentation":"Thrown while converting an ESTree BigIntLiteral into swc's BigInt node (swc_estree_compat `swcify`). The `value` string is passed straight to `num_bigint::BigInt::from_str`, which only accepts an optional sign followed by plain decimal digits; anything else returns Err and the `.expect(...)` panics, aborting the process. ESTree producers (acorn) put the raw literal text in `value`, e.g. \"123n\", and that trailing 'n' alone makes the parse fail. Radix prefixes (0x/0b/0o), underscores, whitespace, and empty strings fail the same way.","triggerScenarios":"Calling `.swcify(ctx)` (directly or via a full estree->swc AST conversion) on a tree containing a BigInt literal whose `value` is not bare decimal digits: acorn-style value=\"123n\", value=\"0xffn\", value=\"1_000n\", value=\"\", or value with surrounding whitespace.","commonSituations":"Feeding acorn / estree-toolkit / serialized ESTree JSON into swc_estree_compat; AST producers that keep the suffix in `value` instead of using acorn's dedicated `bigint` field; hand-written AST fixtures with placeholder values; partial/malformed ASTs where value was never populated.","solutions":["Normalize the value before converting: strip a trailing 'n' (and any radix prefix / '_' separators) so only an optional sign plus decimal digits remain","If the AST came from acorn, copy the `bigint` property (digits only) into `value` before swcify","If you build the ESTree AST yourself, emit value as the digits-only decimal string","Patch the crate to use a fallible conversion (map the Err into a diagnostic instead of expect) and report the upstream issue"],"exampleFix":"// before\n// node = acorn BigIntLiteral: { type: 'BigIntLiteral', value: '9007199254740993n', bigint: '9007199254740993' }\nswcify(node); // panics: failed to parse the value of BigIntLiteral\n\n// after\nif (node.type === 'BigIntLiteral' && node.bigint != null) {\n  node.value = node.bigint; // digits only, no 'n'\n}\nswcify(node);","handlingStrategy":"validation","validationCode":"// before swcify, check every BigIntLiteral value parses as a bigint\nfunction bigintValueOk(node) {\n  if (node.type !== 'BigIntLiteral') return true;\n  const digits = String(node.value).replace(/n$/, '');\n  return /^[+-]?\\d+$/.test(digits);\n}\nconst bad = nodes.filter(n => !bigintValueOk(n));\nif (bad.length) throw new Error(`unparseable BigIntLiteral value: ${bad[0].value}`);","typeGuard":"function isParseableBigIntLiteral(node: unknown): boolean {\n  if (typeof node !== 'object' || node === null) return false;\n  const n = node as { type?: string; value?: unknown; bigint?: unknown };\n  if (n.type !== 'BigIntLiteral') return false;\n  if (typeof n.bigint === 'string') return /^[+-]?\\d+$/.test(n.bigint);\n  return typeof n.value === 'string' && /^[+-]?\\d+$/.test(n.value.replace(/n$/, ''));\n}","tryCatchPattern":"// Rust callers can keep the panic from aborting the process:\nlet converted = std::panic::catch_unwind(|| estree_ast.swcify(&ctx))\n    .map_err(|p| panic_message(&p)) // convert to a normal error\n    .and_then(|ast| Ok(ast));\n// prefer pre-validating values instead; catch_unwind is a last resort","preventionTips":["When consuming acorn output, always overwrite node.value with node.bigint for BigIntLiteral","Validate the tree with a JSON-schema or AST walker that checks numeric-literal value formats before conversion","In CI, round-trip a small corpus containing bigint literals through the estree->swc conversion"],"tags":["bigint","estree-compat","parse","panic","swcify","rust"],"backgroundTag":"invalid-numeric-literal-string","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}