different-ai/openwork · error · InterpreterRuntimeError
Expected '${key}' to be a string.
Error message
Expected '${key}' to be a string. What it means
getString reads a property off an AstNode and asserts it is a string, throwing InterpreterRuntimeError (node attached) otherwise. It guards literal values, identifiers, operator names, etc., so a non-string (undefined, number, object) means the AST node lacks or misnames the expected field.
Source
Thrown at packages/codemode/src/interpreter/model.ts:174
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]
if (typeof value !== "boolean") throw new InterpreterRuntimeError(`Expected '${key}' to be a boolean.`, node)
return value
}
export const getOptionalNode = (node: AstNode, key: string): AstNode | undefined => {
const value = node[key]
if (value === undefined || value === null) return undefined
return asNode(value, key)
}
export const getNode = (node: AstNode, key: string): AstNode => asNode(node[key], key)
export const sourceLocation = (node: AstNode): { readonly line: number; readonly column: number } => ({View on GitHub (pinned to 2b7df46e8a)
Solutions
- Check the node's actual shape (the error attaches the node) and use the correct key
- If the value is a nested node, retrieve it with getNode/asNode and read its string field instead
- Match parser and interpreter versions so field encodings agree
- Use getOptional-style access or check key existence for optional string fields
Example fix
// before const name = getString(callNode, "callee") // callee is a node // after const name = getString(asNode(callNode.callee, "callee"), "name")
Defensive patterns
Strategy: type-guard
Validate before calling
const v = node[key]
if (typeof v !== "string") {
throw new Error(`Expected string at node.${key}, got ${typeof v}`)
}
getString(node, key) Type guard
const hasStringField = (node: AstNode, key: string): boolean => typeof node[key] === "string"
Try / catch
try {
name = getString(node, "name")
} catch (e) {
if (e instanceof InterpreterRuntimeError && e.message.includes("to be a string")) {
// value may be a nested Identifier node; resolve its name instead
name = node["name"] && typeof node["name"] === "object" ? getString(node["name"] as AstNode, "name") : null
} else throw e
} Prevention
- Read nested identifiers via getNode + getString('name') instead of expecting a flat string
- Check node kind before reading kind-specific string fields
- Keep parser/interpreter versions aligned so field encodings agree
- Log the attached node on failure — it names the exact construct that diverged
When it happens
Trigger: Calling getString(node, key) where node[key] is undefined (missing/typo'd key), a number (numeric literal stored as number), or another non-string type — e.g. getString(callNode, "callee") on a node whose callee is a nested node, not a name.
Common situations: Grammar mismatch between parser and interpreter versions; expecting an identifier name where the parser stores a nested Identifier node; accessing a key absent on that node kind (e.g. reading `name` off a node type that has no name).
Related errors
- Expected '${key}' to be an array.
- Expected '${key}' to be a boolean.
- Invalid AST node while reading ${context}.
- Failed to parse script as a Program node.
- String.${name} expects argument ${index + 1} to be a string.
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/ecf12608ff927c17.
Report an issue: GitHub.