different-ai/openwork · error · InterpreterRuntimeError

Expected ' ' 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.

Solutions

  1. Check the node's actual shape (the error attaches the node) and use the correct key
  2. If the value is a nested node, retrieve it with getNode/asNode and read its string field instead
  3. Match parser and interpreter versions so field encodings agree
  4. 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

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


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/ecf12608ff927c17. Report an issue: GitHub.

Appendix: 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)