nanocoai/nanoclaw · error · StdinJsonInputError
--stdin-json input must be one JSON object
Error message
--stdin-json input must be one JSON object
What it means
The --stdin-json input parsed successfully but is not a single JSON object — arrays, scalars, null, and non-objects are rejected because args must be a key/value map.
Source
Thrown at src/cli/stdin-json.ts:76
return Buffer.concat(chunks, byteLength).toString('utf8');
}
/** Parse the input, requiring exactly one JSON object — not an array, scalar, or null. */
function parseJsonObject(source: string): Record<string, unknown> {
if (source.trim().length === 0) {
throw new StdinJsonInputError('--stdin-json input is empty');
}
let parsed: unknown;
try {
parsed = JSON.parse(source);
} catch (err) {
throw new StdinJsonInputError('--stdin-json input is not valid JSON', { cause: err });
}
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
throw new StdinJsonInputError('--stdin-json input must be one JSON object');
}
return parsed as Record<string, unknown>;
}
/** Match the key normalization applied by command parsers in crud.ts. */
function canonicalArgKey(key: string): string {
return key.replace(/-/g, '_');
}
/**
* Reject any stdin key that could collide with another arg after the merge.
*
* Command parsers (crud.ts) normalize `-` to `_` in arg keys, so `group-id`
* and `group_id` are the same argument downstream. Two keys that are distinct
* here but identical after normalization would silently overwrite each other
* past this point — so every such alias is a hard conflict, whether the pair
* is stdin-vs-argv or two stdin keys.View on GitHub (pinned to 294ef2aee8)
Solutions
- Wrap the data in an object with the intended argument keys
- For arrays, loop in shell and invoke the command per element
Example fix
# before
echo '[{"name":"a"},{"name":"b"}]' | ncl groups create --stdin-json
# after
for n in a b; do echo "{\"name\":\"$n\"}" | ncl groups create --stdin-json; done Defensive patterns
Strategy: type-guard
Validate before calling
const obj = JSON.parse(src);
if (Array.isArray(obj) || typeof obj !== 'object' || obj === null) throw new Error('need one object'); Type guard
function isJsonObject(x: unknown): x is Record<string, unknown> {
return typeof x === 'object' && x !== null && !Array.isArray(x);
} Prevention
- Wrap batch items in a loop of single-object invocations
When it happens
Trigger: Piping `[...]`, `"string"`, `42`, `true`, or `null` to --stdin-json.
Common situations: Piping a JSON array of records expecting batch create, or a jq filter that emits a scalar/string.
Related errors
- --stdin-json input exceeds ${MAX_STDIN_JSON_BYTES} bytes
- --stdin-json input is empty
- --stdin-json input is not valid JSON
- --stdin-json key "__proto__" is not allowed
- --stdin-json key "${key}" is also supplied on argv
AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28).
Data as JSON: /api/errors/608d7095cdbbb0cf.
Report an issue: GitHub.