different-ai/openwork · error · InterpreterRuntimeError
Object.assign expects data objects.
Error message
Object.assign expects data objects.
What it means
The Object.assign branch validates every source argument is a plain data object (not null, undefined — those are skipped — not array, not primitive, not sandbox value) and throws this when a source fails the check, matching the assign-specific requireObject semantics.
Source
Thrown at packages/codemode/src/stdlib/object.ts:45
if (value === null || typeof value !== "object") {
throw new InterpreterRuntimeError("Object.keys expects a data object or array.", node)
}
return Object.keys(value)
}
case "values":
return Object.values(requireObject())
case "entries":
return Object.entries(requireObject()).map(([key, item]) => [key, item])
case "hasOwn":
return Object.hasOwn(requireObject(), String(args[1]))
case "assign": {
const out: Record<string, unknown> = Object.create(null)
for (const source of args) {
if (source === null || source === undefined) continue
const value = boundedData(source, "Object.assign input")
if (isSandboxValue(value)) continue
if (value === null || typeof value !== "object" || Array.isArray(value)) {
throw new InterpreterRuntimeError("Object.assign expects data objects.", node)
}
for (const [key, item] of Object.entries(value)) guardedSet(out, key, item)
}
return out
}
case "fromEntries": {
if (args[0] instanceof SandboxMap) {
const out: Record<string, unknown> = Object.create(null)
for (const [key, item] of args[0].map.entries()) guardedSet(out, coerceToString(key), item)
return out
}
if (args[0] instanceof SandboxURLSearchParams) {
const out: Record<string, unknown> = Object.create(null)
for (const [key, value] of args[0].params.entries()) guardedSet(out, key, value)
return out
}
const pairs = boundedData(args[0], "Object.fromEntries input")
if (!Array.isArray(pairs)) {View on GitHub (pinned to 2b7df46e8a)
Solutions
- Wrap array sources: Object.assign({}, ...arr) → iterate and index-convert first, or Object.fromEntries(arr.map((v,i)=>[String(i),v]))
- Skip/normalize scalar sources before merging: const src = (v) => (v && typeof v === 'object' && !Array.isArray(v) ? v : {})
- Check the producing function/endpoint for a shape change and fix at the source
- Merge only after validating each input with a plain-object check
Example fix
// before
const merged = Object.assign({}, defaults, apiResult)
// after
const src = apiResult && typeof apiResult === 'object' && !Array.isArray(apiResult) ? apiResult : {}
const merged = Object.assign({}, defaults, src) Defensive patterns
Strategy: validation
Validate before calling
const asPlainObject = (v: unknown): Record<string, unknown> =>
v !== null && typeof v === 'object' && !Array.isArray(v) ? v as Record<string, unknown> : {}
const merged = Object.assign({}, asPlainObject(defaults), asPlainObject(apiResult)) Type guard
const isMergeSource = (v: unknown): v is Record<string, unknown> => v !== null && v !== undefined && typeof v === 'object' && !Array.isArray(v)
Try / catch
try {
return Object.assign({}, source)
} catch (e) {
if (e instanceof InterpreterRuntimeError && e.message.includes('Object.assign expects data objects')) {
return Object.assign({}, normalizeSource(source))
}
throw e
} Prevention
- Normalize each assign source to a plain object first
- Watch endpoints whose response shape changed object→array
- Skip null/undefined sources explicitly (assign already tolerates them)
- Add shape assertions at API boundaries
When it happens
Trigger: Object.assign({}, [1,2]) (array source), Object.assign({}, 42), Object.assign({}, 'str'), Object.assign(target, someArrayResponse) where an upstream call returned an array instead of an object.
Common situations: Merging defaults with an API result that is occasionally an array; spreading array-likes into config; a renamed endpoint changed the response shape from object to list.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Object.${name} expects a data object.
- Object.keys expects a data object or array.
- Object.fromEntries expects an array of [key, value] pairs.
- Object.fromEntries expects [key, value] pairs.
- String.${name} expects argument ${index + 1} to be a number.
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/6f312a7e593b0c67.
Report an issue: GitHub.