{"record":{"id":"b8c6084613543e10","repo":"different-ai/openwork","slug":"expected-key-to-be-a-boolean","errorCode":null,"errorMessage":"Expected '${key}' to be a boolean.","messagePattern":"Expected '(.+?)' to be a boolean\\.","errorType":"exception","errorClass":"InterpreterRuntimeError","httpStatus":null,"severity":"error","filePath":"packages/codemode/src/interpreter/model.ts","lineNumber":180,"sourceCode":"  }\n  return value as AstNode\n}\n\nexport const getArray = (node: AstNode, key: string): Array<unknown> => {\n  const value = node[key]\n  if (!Array.isArray(value)) throw new InterpreterRuntimeError(`Expected '${key}' to be an array.`, node)\n  return value\n}\n\nexport const getString = (node: AstNode, key: string): string => {\n  const value = node[key]\n  if (typeof value !== \"string\") throw new InterpreterRuntimeError(`Expected '${key}' to be a string.`, node)\n  return value\n}\n\nexport const getBoolean = (node: AstNode, key: string): boolean => {\n  const value = node[key]\n  if (typeof value !== \"boolean\") throw new InterpreterRuntimeError(`Expected '${key}' to be a boolean.`, node)\n  return value\n}\n\nexport const getOptionalNode = (node: AstNode, key: string): AstNode | undefined => {\n  const value = node[key]\n  if (value === undefined || value === null) return undefined\n  return asNode(value, key)\n}\n\nexport const getNode = (node: AstNode, key: string): AstNode => asNode(node[key], key)\n\nexport const sourceLocation = (node: AstNode): { readonly line: number; readonly column: number } => ({\n  line: Math.max(1, (node.loc?.start.line ?? 2) - 1),\n  column: Math.max(1, (node.loc?.start.column ?? 4) - 3),\n})\n\nexport const formatLocation = (node?: AstNode): string => {\n  if (!node?.loc) return \"\"","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/packages/codemode/src/interpreter/model.ts#L162-L198","documentation":"getBoolean is an internal AST accessor in the CodeMode interpreter that extracts an AST node property and asserts it is a boolean. It throws InterpreterRuntimeError when a node field that the interpreter expects to be `true`/`false` (e.g. a literal's `value`, a declaration's flag fields) has any other type, meaning the AST shape differs from what the evaluator assumes. This indicates either a malformed/synthetic AST node was fed to the interpreter or an internal bug in how a node was constructed.","triggerScenarios":"Calling program()/run with TypeScript that transpiles to an AST where a node property read via getBoolean (e.g. a BooleanLiteral's value) is not a boolean — typically when custom/transpiled AST is injected, or an interpreter bug after an AST producer version change.","commonSituations":"Running scripts through a mismatched typescript transpile target/AST shape, manually constructing AST nodes, or a codemode package version where AST fields were renamed so old field values are undefined.","solutions":["Update packages/codemode to a matching version so the transpiler output and interpreter AST accessors agree.","Check the node reported in the error: log node[key] and confirm the field actually holds a boolean.","If constructing AST by hand, set the field to a real boolean (true/false) rather than a string like \"true\".","File/report an interpreter bug if the input script is plain valid TypeScript that should never hit this path."],"exampleFix":"// before (synthetic node)\nconst node = { type: \"BooleanLiteral\", value: \"true\" }\n// after\nconst node = { type: \"BooleanLiteral\", value: true }","handlingStrategy":"try-catch","validationCode":"// Before running, sanity-check that scripts you feed in are plain TS that transpiles cleanly:\nimport ts from \"typescript\"\nconst { diagnostics } = ts.transpileModule(script, { compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ESNext } })\nif (diagnostics?.length) throw new Error(\"Script does not transpile cleanly\")","typeGuard":"const isBoolean = (v: unknown): v is boolean => typeof v === \"boolean\"","tryCatchPattern":"try {\n  await program(script)\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"to be a boolean\")) {\n    // internal AST shape mismatch: report script + interpreter version, don't retry blindly\n  } else throw e\n}","preventionTips":["Keep packages/codemode and its transpiler dependency versions in sync via the lockfile.","Never hand-construct AST nodes fed to the interpreter; always parse from source text.","Pin the typescript version codemode was built against when generating scripts programmatically.","Run a canary script through program() in CI to catch interpreter/AST drift early."],"tags":["interpreter","ast","type-mismatch","codemode"],"backgroundTag":"ast-node-type-mismatch","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}