nanocoai/nanoclaw · error · Error
${msg} ${usage}
Error message
${msg}
${usage} What it means
This is not a distinct failure but the wrapper around strict validation for custom verbs: any validateArgs failure (unknown flag, required, type, JSON, enum) is re-thrown with the verb's rendered usage block appended, separated by a blank line, and the original error preserved as `cause`. It exists so a human or agent caller can fix the invocation in one round-trip instead of issuing a separate help command.
Source
Thrown at src/cli/crud.ts:544
// can fix the invocation without a second help round-trip.
if (def.customOperations) {
for (const [verb, op] of Object.entries(def.customOperations)) {
const declared = op.args;
register({
name: `${def.plural}-${verb.replace(/ /g, '-')}`,
action: `${def.plural}.${verb.replace(/ /g, '.')}`,
description: op.description,
access: op.access,
hostOnly: op.hostOnly,
resource: def.plural,
parseArgs: declared
? (raw) => {
try {
return validateArgs(declared, normalizeArgs(raw));
} catch (e) {
const usage = renderVerbHelp(def, verb);
const msg = e instanceof Error ? e.message : String(e);
throw new Error(usage ? `${msg}\n\n${usage}` : msg, { cause: e });
}
}
: (raw) => normalizeArgs(raw),
handler: async (args, ctx) => op.handler(args as Record<string, unknown>, ctx),
formatHuman: op.formatHuman,
});
}
}
}
View on GitHub (pinned to 294ef2aee8)
Solutions
- Read the full message — the usage block after the blank line lists accepted flags and required markers
- Fix the underlying validation issue named on the first line
- Programmatically, inspect `error.cause` for the original un-wrapped validation error
- For tests, assert with `.startsWith()` or match on the first line only
Example fix
// before (test asserts exact message)
expect(() => parse(args)).toThrow('unknown flag --rebild');
// after
expect(() => parse(args)).toThrow(/^unknown flag --rebild/); Defensive patterns
Strategy: try-catch
Validate before calling
null
Try / catch
catch (e) {
if (e instanceof Error) {
const [first, usage] = e.message.split('\n\n');
// first line = underlying validation error; usage = rendered help
const root = e.cause; // original validateArgs error
}
} Prevention
- Parse the message on the first line; render the usage block to the user
- In tests, match messages with startsWith/regex, not exact equality
- Use error.cause to get the unwrapped validation error programmatically
When it happens
Trigger: Any of errors 32–38 occurring on a custom operation (a verb defined in `customOperations` with declared `args`). E.g. `ncl groups restart --id g1 --mesage x` produces "unknown flag --mesage" plus the restart usage text.
Common situations: Parsers that split the error on newlines and only surface the first line lose the usage context; agents that retry blindly instead of reading the appended usage; tests asserting exact error strings breaking when usage is appended.
Related errors
- unknown flag --${key.replace(/_/g, '-')}
- ${flag} is required
- ${flag} requires a value
- ${flag} must be a number, got "${v}"
- ${flag} must be true or false, got "${v}"
AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28).
Data as JSON: /api/errors/903d5409ce29c2cf.
Report an issue: GitHub.