affaan-m/ECC · error · Error
orch-review: args must be an object
Error message
orch-review: args must be an object
What it means
After JSON decoding, the workflow requires the resulting input to be an object. JSON primitives like numbers, strings, booleans, or arrays parsed from a JSON string (or a raw number/boolean passed directly) are rejected, again failing closed rather than reviewing the wrong shape.
Solutions
- Wrap the payload in an object with the expected keys, e.g. { diff, changedFiles }.
- If passing JSON text, ensure it decodes to an object: '{"diff": ...}' not '...'.
- Inspect the caller: a variable shadowing or type coercion may be replacing the object with a primitive.
Example fix
// before
runWorkflow('orch-review', 'just the diff text');
// after
runWorkflow('orch-review', { diff: 'just the diff text' }); Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof payload !== 'object' || payload === null || Array.isArray(payload)) {
throw new Error('orch-review payload must be a plain object');
} Type guard
const isPlainObject = v => v !== null && typeof v === 'object' && !Array.isArray(v);
Try / catch
try {
const result = await orchReview(args);
} catch (err) {
if (err.message === 'orch-review: args must be an object') {
console.error('Wrap the payload: { diff, changedFiles }.');
} else throw err;
} Prevention
- Always pass { diff, changedFiles } as an object; never the diff string itself.
- Avoid double-encoding: if the caller JSON.stringifies, do not stringify again downstream.
- Add an integration test asserting the payload shape before the workflow is called.
When it happens
Trigger: Passing args = 42, '"a string"', true, or a JSON string like '[1,2]' or 'null'-adjacent primitives such that typeof input !== 'object' (note: JSON strings that parse to arrays also fail this check).
Common situations: Callers passing the diff content itself instead of a wrapper object; wrappers double-encoding a payload; CLI arg parsing that converts the payload to a number/boolean; copying an array-based payload from another tool's API.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- orch-review: args.changedFiles must be an array of paths
- orch-review: args.changedFiles must contain only string…
- Canonical session snapshot must be an object
- Canonical session snapshot requires
- Canonical session snapshot requires
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/84ad626a9ab4ec8d.
Report an issue: GitHub.
Appendix: source
Thrown at workflows/orch-review.workflow.js:159
diff,
'----- END DIFF -----'
].join('\n');
}
// --- main -----------------------------------------------------------------
// `args` arrives verbatim. Accept a JSON-encoded string too, so the workflow
// works whether the caller passes an object or a stringified payload.
// Fail CLOSED on invalid input: a review gate must never silently APPROVE a
// payload it could not actually review.
let input;
try {
input = typeof args === 'string' ? JSON.parse(args) : (args ?? {});
} catch {
throw new Error('orch-review: args must be an object or valid JSON');
}
if (typeof input !== 'object' || input === null) {
throw new Error('orch-review: args must be an object');
}
if (typeof input.diff !== 'string' || input.diff.trim() === '') {
throw new Error('orch-review: args.diff must be a non-empty unified diff');
}
if (input.changedFiles != null && !Array.isArray(input.changedFiles)) {
throw new Error('orch-review: args.changedFiles must be an array of paths');
}
// Every entry must be a string path. A non-string (e.g. { path: '...' }) would
// stringify to "[object Object]" and silently poison the security-trigger
// haystack — fail closed on malformed input instead.
if (Array.isArray(input.changedFiles) && !input.changedFiles.every(f => typeof f === 'string')) {
throw new Error('orch-review: args.changedFiles must contain only string paths');
}
const diff = input.diff;
const haystack = `${diff}\n${(input.changedFiles || []).join('\n')}`;
// Build the review dimensions immutably. Quality always runs; language +View on GitHub (pinned to 8321021c54)