{"record":{"id":"48a46afcc1c2e42e","repo":"swc-project/swc","slug":"unknown-statement-type-stmt-as-any-type","errorCode":null,"errorMessage":"Unknown statement type: ${(stmt as any).type","messagePattern":"Unknown statement type: \\$\\{\\(stmt as any\\)\\.type","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/Visitor.ts","lineNumber":515,"sourceCode":"            case \"LabeledStatement\":\n                return this.visitLabeledStatement(stmt);\n            case \"ReturnStatement\":\n                return this.visitReturnStatement(stmt);\n            case \"SwitchStatement\":\n                return this.visitSwitchStatement(stmt);\n            case \"ThrowStatement\":\n                return this.visitThrowStatement(stmt);\n            case \"TryStatement\":\n                return this.visitTryStatement(stmt);\n            case \"WhileStatement\":\n                return this.visitWhileStatement(stmt);\n            case \"WithStatement\":\n                return this.visitWithStatement(stmt);\n            case \"ExpressionStatement\":\n                return this.visitExpressionStatement(stmt);\n\n            default:\n                throw new Error(\n                    `Unknown statement type: ` + (stmt as any).type\n                );\n        }\n    }\n\n    visitSwitchStatement(stmt: SwitchStatement): Statement {\n        stmt.discriminant = this.visitExpression(stmt.discriminant);\n        stmt.cases = this.visitSwitchCases(stmt.cases);\n        return stmt;\n    }\n\n    visitSwitchCases(cases: SwitchCase[]): SwitchCase[] {\n        return cases.map(this.visitSwitchCase.bind(this));\n    }\n\n    visitSwitchCase(c: SwitchCase): SwitchCase {\n        c.test = this.visitOptionalExpression(c.test);\n        c.consequent = this.visitStatements(c.consequent);","sourceCodeStart":497,"sourceCodeEnd":533,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/packages/core/src/Visitor.ts#L497-L533","documentation":"Thrown by the legacy JavaScript `Visitor` base class that @swc/core exposes for legacy `plugin` callbacks. visitStatement() is a switch over a fixed enumeration of statement `type` strings (base ES statements plus TsEnum/TsInterface/TsModule/TsTypeAlias declarations); any statement type not in that list falls into `default` and throws `Unknown statement type: <type>`. The enumeration predates newer and less-common AST nodes, so walking modern syntax through a legacy plugin crashes instead of visiting it.","triggerScenarios":"A legacy plugin (options.plugin using `new MyVisitor().visitProgram(program)`) walking an AST that contains a statement node type absent from the switch — a node kind introduced after this visitor was written, or a hand-built/modified AST whose statement `type` strings are misspelled or non-standard.","commonSituations":"Reusing an old JS plugin written for plain JS with a current @swc/core on modern syntax; prototypes that synthesize AST nodes manually; upgrading @swc/core under a plugin that used to work, exposing node types the legacy switch never knew.","solutions":["Override visitStatement in your subclass: delegate to super.visitStatement inside try/catch and return the statement untouched when the message starts with 'Unknown statement type:'","Or copy the switch into your override and add a `default` that handles/returns the new node type instead of throwing","Migrate off the legacy Visitor to the current plugin/visitor API, which dispatches over the full modern AST","Pre-transform the input (e.g. strip newer syntax) before handing the Program to the legacy plugin"],"exampleFix":"// before\nclass MyVisitor extends Visitor {\n    visitIdentifier(n) { /* ... */ return n; }\n}\n// -> Error: Unknown statement type: ...\n\n// after\nclass MyVisitor extends Visitor {\n    visitStatement(stmt) {\n        try {\n            return super.visitStatement(stmt);\n        } catch (e) {\n            if (e instanceof Error && e.message.startsWith('Unknown statement type:')) {\n                return stmt; // pass unrecognized statements through untouched\n            }\n            throw e;\n        }\n    }\n}","handlingStrategy":"try-catch","validationCode":"// Dry-run the legacy visitor over a deep clone; if it throws on an unknown\n// statement type, skip or reroute the plugin instead of failing the build.\nconst { Visitor } = require('@swc/core');\nfunction legacyVisitorSupports(program) {\n  try {\n    new Visitor().visitProgram(structuredClone(program));\n    return true;\n  } catch (e) {\n    return !(e instanceof Error && e.message.startsWith('Unknown statement type:'));\n  }\n}","typeGuard":null,"tryCatchPattern":"class SafeVisitor extends Visitor {\n  visitStatement(stmt) {\n    try {\n      return super.visitStatement(stmt);\n    } catch (e) {\n      if (e instanceof Error && e.message.startsWith('Unknown statement type:')) {\n        return stmt; // pass through nodes this legacy visitor doesn't know\n      }\n      throw e;\n    }\n  }\n}","preventionTips":["Prefer the current plugin/visitor API over the legacy Visitor class when handling modern syntax","Pin the @swc/core version a legacy plugin was written against, and re-test after upgrades","Run the plugin over your full real corpus in CI so unknown node types surface before production"],"tags":["swc","legacy-plugin","visitor","ast","javascript-plugin"],"backgroundTag":"unknown-ast-node-type","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}