affaan-m/ECC · error · Error
ECC_PROJECT_DIR must be a child path within /workspace.
Error message
ECC_PROJECT_DIR must be a child path within /workspace.
What it means
The orch-review workflow is a fail-closed review gate: it validates its args payload before approving anything. This throw fires when args is a string that cannot be parsed as JSON. The workflow accepts either a plain object or a JSON-encoded string, but a malformed string is rejected outright so the gate never silently approves a payload it could not actually inspect.
Source
Thrown at docker/plugin-setup/resolve-project-dir.js:20
'use strict';
const path = require('path');
const WORKSPACE_ROOT = '/workspace';
function resolveProjectDir(candidate) {
if (
typeof candidate !== 'string'
|| !path.posix.isAbsolute(candidate)
|| /[\0\r\n]/.test(candidate)
) {
throw new Error('ECC_PROJECT_DIR must be an absolute path within /workspace.');
}
const resolved = path.posix.resolve(candidate);
if (resolved === WORKSPACE_ROOT || !resolved.startsWith(`${WORKSPACE_ROOT}/`)) {
throw new Error('ECC_PROJECT_DIR must be a child path within /workspace.');
}
return resolved;
}
function main() {
try {
process.stdout.write(`${resolveProjectDir(process.argv[2])}\n`);
} catch (error) {
process.stderr.write(`Error: ${error.message}\n`);
process.exitCode = 2;
}
}
if (require.main === module) main();
module.exports = { resolveProjectDir };
View on GitHub (pinned to 01e15490f0)
Solutions
- Pass a plain JS object instead of a string: orchReview({ diff, changedFiles }).
- If you must pass a string, build it with JSON.stringify(payload) so it is always valid JSON.
- Pre-validate the string with JSON.parse in your caller and surface the parse error before invoking the workflow.
Example fix
// before
orchReview('{diff: "+++", changedFiles: ["a.js"]}'); // invalid JSON keys
// after
orchReview({ diff: '+++', changedFiles: ['a.js'] }); // pass an object Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate a string payload before calling the workflow.
let payload = args;
if (typeof payload === 'string') {
try { payload = JSON.parse(payload); }
catch { throw new Error('args is not valid JSON — pass an object or JSON.stringify first'); }
} Type guard
// Ensure args is a plain object before invoking the review gate.
function isPlainObject(v) {
return typeof v === 'object' && v !== null && !Array.isArray(v);
} Try / catch
try {
orchReview(args);
} catch (e) {
if (e.message.startsWith('orch-review: args must be an object or valid JSON')) {
// Rebuild the payload as a guaranteed-valid object and retry, or surface to caller.
}
throw e;
} Prevention
- Always pass a plain JS object, not a hand-built JSON string.
- When you must serialize, use JSON.stringify — never template JSON by hand.
- Treat any orch-review input error as a caller bug, not a transient failure.
When it happens
Trigger: Calling orchReview("{diff: '...'}") (unquoted keys = invalid JSON); orchReview("diff: ...") (plain text, not JSON); orchReview("[broken") (truncated); shell quoting mangles a stringified payload into invalid JSON.
Common situations: Caller hand-builds a JSON string instead of JSON.stringify-ing an object; a shell heredoc or variable expansion breaks the JSON; a templating layer emits JS-object literal syntax instead of JSON.
Related errors
- Unknown argument: ${arg}
- Unable to infer ECC repo root from install-state operations
- Invalid ECC repo root: missing package.json at ${packageJson
- Invalid ECC repo root: missing install script at ${installAp
- --json may only be provided once
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/b53a66d582f3d4ba.
Report an issue: GitHub.