different-ai/openwork · error · InterpreterRuntimeError
Invalid AST node while reading ${context}.
Error message
Invalid AST node while reading ${context}. What it means
asNode narrows an unknown value to an AstNode before the interpreter reads properties off it. A valid node must be a non-null object with a string `type` field. Malformed AST fragments (primitives, null, objects missing `type`) throw InterpreterRuntimeError with the reading context included for debugging.
Source
Thrown at packages/codemode/src/interpreter/model.ts:161
this.errorName = errorName
return this
}
}
export const unsupportedSyntax = (kind: string, node: AstNode): InterpreterRuntimeError =>
new InterpreterRuntimeError(
`Syntax '${kind}' is not supported in CodeMode. ${supportedSyntaxMessage}`,
node,
"UnsupportedSyntax",
[supportedSyntaxMessage],
)
export const isRecord = (value: unknown): value is Record<string, unknown> =>
typeof value === "object" && value !== null
export const asNode = (value: unknown, context: string): AstNode => {
if (!isRecord(value) || typeof value.type !== "string") {
throw new InterpreterRuntimeError(`Invalid AST node while reading ${context}.`)
}
return value as AstNode
}
export const getArray = (node: AstNode, key: string): Array<unknown> => {
const value = node[key]
if (!Array.isArray(value)) throw new InterpreterRuntimeError(`Expected '${key}' to be an array.`, node)
return value
}
export const getString = (node: AstNode, key: string): string => {
const value = node[key]
if (typeof value !== "string") throw new InterpreterRuntimeError(`Expected '${key}' to be a string.`, node)
return value
}
export const getBoolean = (node: AstNode, key: string): boolean => {
const value = node[key]View on GitHub (pinned to 2b7df46e8a)
Solutions
- Check the child exists before reading it (use getOptionalNode for optional fields)
- Verify the AST comes from the parser version the interpreter expects; regenerate the parse
- Log the `context` argument in the error message to find which AST access path produced the malformed value
- If constructing nodes manually, always include { type: <nodeKind>, ... }
Example fix
// before const target = asNode(node.expression, "expression") // undefined when absent // after const target = node.expression !== undefined ? asNode(node.expression, "expression") : null
Defensive patterns
Strategy: type-guard
Validate before calling
const looksLikeNode = (v: unknown): boolean => typeof v === "object" && v !== null && typeof (v as Record<string, unknown>).type === "string" // before reading a child: if (!node.body || !looksLikeNode(node.body)) skip
Type guard
const isAstNode = (v: unknown): v is AstNode => typeof v === "object" && v !== null && typeof (v as Record<string, unknown>).type === "string"
Try / catch
try {
const child = getNode(node, "body")
} catch (e) {
if (e instanceof InterpreterRuntimeError && e.message.startsWith("Invalid AST node")) {
logAstAnomaly(node) // capture offending subtree + context from message
return null
}
throw e
} Prevention
- Pin parser and interpreter to compatible versions so AST shapes match
- Always include a string `type` on hand-constructed nodes
- Validate deserialized AST JSON with a schema (zod) before interpretation
- Use getOptionalNode for fields that may legitimately be absent
When it happens
Trigger: Calling asNode (directly or via getNode/getOptionalNode) with null, undefined, a primitive, an array, or an object lacking a string `type` — typically while traversing a parsed program, e.g. asNode(node.body, "statement body") where body is not a node.
Common situations: A parser/parser-version mismatch producing an AST shape the interpreter doesn't expect; hand-written or programmatically generated AST fragments missing `type`; deserialized JSON ASTs that lost the type field; optional child accessed when absent.
Related errors
- Expected '${key}' to be an array.
- Expected '${key}' to be a string.
- Expected '${key}' to be a boolean.
- Failed to parse script as a Program node.
- The right-hand side of 'instanceof' must be a constructor Co
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/6d177704cdf2b6fc.
Report an issue: GitHub.