different-ai/openwork · error · ToolRuntimeError
InvalidDataValue
InvalidDataValue
Error message
${label} exceeds the maximum value depth of ${MAX_VALUE_DEPTH}. What it means
CodeMode bounds every value crossing the tool/interpreter boundary (copyIn/copyBounded/copied) to a maximum nesting depth (MAX_VALUE_DEPTH). Deeply nested objects/arrays beyond that limit are rejected with this InvalidDataValue ToolRuntimeError to prevent stack exhaustion and runaway memory when copying values in or out of the sandbox.
Source
Thrown at packages/codemode/src/tool-runtime.ts:182
* - **Intra-sandbox checkpoint** (`preserveSandboxValues` true; see `boundedData` in
* codemode.ts): standard-library value instances pass through untouched (treated as leaves,
* contents not walked), so values flowing through `Object.*` helpers, coercion inputs, and
* other in-sandbox checkpoints stay fully usable (`.getTime()`, `.has()`, ...).
*
* Both modes reject un-awaited promises with an await-hinting diagnostic.
*/
export const copyIn = (value: unknown, label: string, preserveSandboxValues = false): unknown =>
copyBounded(value, label, 0, new Set(), preserveSandboxValues)
const copyBounded = (
value: unknown,
label: string,
depth: number,
seen: Set<object>,
preserveSandboxValues: boolean,
): unknown => {
if (depth > MAX_VALUE_DEPTH) {
throw new ToolRuntimeError("InvalidDataValue", `${label} exceeds the maximum value depth of ${MAX_VALUE_DEPTH}.`)
}
if (
value === null ||
value === undefined ||
typeof value === "string" ||
typeof value === "boolean" ||
// NaN/Infinity are allowed to exist as in-sandbox intermediates (matching real JS and a real
// engine) so defensive guards like `Number.isNaN(x)` / `parseInt(x) || 0` can run. They are
// normalized to `null` when the value leaves the sandbox - see copyOut - exactly as
// JSON.stringify already does at any tool boundary.
typeof value === "number"
) {
return value
}
if (typeof value !== "object") {
throw new ToolRuntimeError("InvalidDataValue", `${label} must contain data only.`)
}View on GitHub (pinned to 2b7df46e8a)
Solutions
- Flatten the data before passing it (e.g. JSON round-trip after removing cycles, or serialize rows instead of a nested tree).
- Break cycles before copying: track visited nodes and replace back-references with ids.
- Select only the needed subset of fields to reduce depth.
- Raise MAX_VALUE_DEPTH only deliberately, understanding the stack/memory cost.
Example fix
// before
tool.run({ tree: cyclicNode }) // circular/deep
// after
const safe = JSON.parse(JSON.stringify(cyclicNode, (k, v) => v === cyclicNode.parent ? null : v))
tool.run({ tree: safe }) Defensive patterns
Strategy: validation
Validate before calling
function depth(v, d = 0, seen = new Set()) {
if (d > 16 || (typeof v === "object" && v !== null && seen.has(v))) throw new RangeError("too deep or circular")
if (typeof v === "object" && v !== null) { seen.add(v); for (const k of Object.keys(v)) depth(v[k], d + 1, seen) }
return v
} Type guard
const isShallowEnough = (v, max = 16) => { try { depth(v, 0, new Set()); return true } catch { return false } } Try / catch
try { sandboxArgs = copyIn(data) } catch (e) { if (e.code === "InvalidDataValue") sandboxArgs = copyIn(flatten(data)) } Prevention
- Strip cycles before passing data across the boundary
- Project only needed fields to keep trees shallow
- Sanitize deep ORM/graph results before tool calls
When it happens
Trigger: Passing a self-referential or very deeply nested object as a tool argument or return value; a linked-list-like structure built by recursive code; circular JSON-style data.
Common situations: Host tool returns a deep ORM/graph result; recursive algorithms build structures deeper than the limit; accidental circular references in cached objects.
Related errors
- String method '${name}' is not available in CodeMode.
- Array.from(...) does not support a map function in CodeMode;
- Array.from expects an array, string, Map, Set, or array-like
- Array.${name} is not available in CodeMode.
- console.${ref.name} is not available in CodeMode.
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/ebaf7f49c843fac5.
Report an issue: GitHub.