n8n-io/n8n · error · Error
Flag ${arg} needs a value
Error message
Flag ${arg} needs a value What it means
Thrown by parseFlags() in build-cost-report.ts:405 when a --flag is followed by either end-of-argv or another --flag token. This lightweight flag parser (a Map<string, string[]>) expects every flag to consume the next token as its value. Unlike the eval CLI parser, this parser does not strip =value payloads and treats any token starting with -- as a new flag rather than a value. The error echoes the flag name (not the value).
Source
Thrown at packages/@n8n/instance-ai/evaluations/cli/build-cost-report.ts:405
'_Cost sources are listed per arm above: persisted `claude` spend is Anthropic-billed' +
' `total_cost_usd` (attempts summed); thread pricing is LangSmith cache-aware pricing' +
' over the build thread’s root runs. Comparable at list price, not identical accountants._',
);
return lines.join('\n');
}
// ---------------------------------------------------------------------------
// CLI
// ---------------------------------------------------------------------------
function parseFlags(argv: string[]): Map<string, string[]> {
const flags = new Map<string, string[]>();
for (let i = 0; i < argv.length; i++) {
const arg = argv[i];
if (!arg.startsWith('--')) continue;
const value = argv[i + 1];
if (value === undefined || value.startsWith('--')) {
throw new Error(`Flag ${arg} needs a value`);
}
const key = arg.slice(2);
const values = flags.get(key);
if (values) values.push(value);
else flags.set(key, [value]);
i++;
}
return flags;
}
/** Last occurrence wins for flags that only make sense once. */
function single(flags: Map<string, string[]>, key: string): string | undefined {
return flags.get(key)?.at(-1);
}
function loadResults(path: string): EvalResults {
return evalResultsSchema.parse(jsonParse(readFileSync(path, 'utf8')));
}View on GitHub (pinned to 5ac6606e81)
Solutions
- Provide a value immediately after each value-taking flag.
- Check for empty shell expansions: `echo "${RESULTS_PATH:?unset}"` before the command.
- If a value legitimately needs to start with --, pass it via a shell variable or restructure to avoid the ambiguity (this parser does not support =value form).
- Re-order so flag-value pairs stay intact.
Example fix
// before pnpm tsx evaluations/cli/build-cost-report.ts --results --label mcp // after pnpm tsx evaluations/cli/build-cost-report.ts --results run/eval-results.json --label mcp
Defensive patterns
Strategy: validation
Validate before calling
const REPORT_VALUE_FLAGS = new Set(['--results','--label','--trace-project','--concurrency','--out','--probe-thread']);
function validateReportFlagValues(args: string[]): void {
for (let i = 0; i < args.length; i++) {
if (REPORT_VALUE_FLAGS.has(args[i])) {
const v = args[i + 1];
if (v === undefined || v.startsWith('--')) {
throw new Error(`Flag ${args[i]} needs a value`);
}
}
}
} Prevention
- Pair every value flag with its value on the same line in scripts.
- Avoid empty shell expansions for flag values.
- This parser does not support =value form — use space-separated values.
When it happens
Trigger: Running build-cost-report.ts with a value-taking flag (--results, --label, --trace-project, --concurrency, --out, --probe-thread) at the end of the command, or immediately before another --flag. For example `--results` as the last token, or `--results --label mcp`.
Common situations: A value was dropped during command editing, a shell expansion produced nothing, or flags were reordered. Also common when a file path value was intended but a glob expanded to nothing leaving the flag value-less.
Related errors
- Pass --results <eval-results.json> (repeatable, one per arm)
- --delete-prebuilt-workflows applies to --prebuilt-workflows.
- ${[...new Set(raw.buildOnlyFlags)].join(', ')} only take${ra
- --delete-prebuilt-workflows requires --prebuilt-workflows
- --delete-prebuilt-workflows cannot be used with --keep-workf
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/23da62f0fe0f06e6.
Report an issue: GitHub.