n8n-io/n8n · error · Error
Pass --results <eval-results.json> (repeatable, one per arm)
Error message
Pass --results <eval-results.json> (repeatable, one per arm) or --probe-thread <id>.
What it means
Thrown by main() in build-cost-report.ts:448 when neither --results nor --probe-thread is provided. The tool has two modes: a multi-arm cost comparison (one or more --results files) or a single-thread connectivity spot-check (--probe-thread <id>). With neither, there is nothing to do, so the parser fails fast with usage guidance.
Source
Thrown at packages/@n8n/instance-ai/evaluations/cli/build-cost-report.ts:448
const probeThread = single(flags, 'probe-thread');
if (probeThread) {
const ls = await langsmithConfig();
const projectId = await resolveTraceProjectId(ls, traceProject);
const cost = await sumThreadCost(ls, projectId, probeThread);
if (!cost) {
console.log(`thread ${probeThread}: no runs found in trace project "${traceProject}"`);
return;
}
console.log(
`thread ${probeThread}: ${cost.turns} turns, ${cost.tokens.toLocaleString()} tokens, ${fmtUsd(cost.costUsd)}`,
);
return;
}
const resultPaths = flags.get('results') ?? [];
const labels = flags.get('label') ?? [];
if (resultPaths.length === 0) {
throw new Error(
'Pass --results <eval-results.json> (repeatable, one per arm) or --probe-thread <id>.',
);
}
// LangSmith access is resolved once, lazily — only when some arm needs the
// thread join (a persisted-spend-only comparison runs without credentials).
let ls: LangSmithConfig | undefined;
let projectId: string | undefined;
const arms: ArmSummary[] = [];
for (let i = 0; i < resultPaths.length; i++) {
const results = loadResults(resultPaths[i]);
const label = labels[i] ?? results.experimentName ?? `arm${String(i + 1)}`;
const hasPersistedSpend = results.testCases.some((tc) => tc.buildCostUsdPerRun !== undefined);
const hasThreads = results.testCases.some((tc) =>
(tc.threadIds ?? []).some((id) => id !== null),
);
if (hasPersistedSpend) {View on GitHub (pinned to 5ac6606e81)
Solutions
- Pass at least one --results <eval-results.json> for a cost comparison report (repeatable, one per arm).
- Or pass --probe-thread <thread-id> for a single-thread cost spot-check.
- Verify any shell variables expanding into --results paths are non-empty: `echo "${RESULTS:?unset}".
Example fix
// before pnpm tsx evaluations/cli/build-cost-report.ts // after pnpm tsx evaluations/cli/build-cost-report.ts --results mcp-run/eval-results.json --results aia-run/eval-results.json --label mcp --label aia
Defensive patterns
Strategy: validation
Validate before calling
function validateReportInputs(args: string[]): void {
const hasResults = args.includes('--results');
const hasProbe = args.includes('--probe-thread');
if (!hasResults && !hasProbe) {
throw new Error('Pass --results <file> or --probe-thread <id>');
}
} Prevention
- Always pass at least one --results or --probe-thread.
- Verify shell expansions producing --results paths are non-empty.
- Use --probe-thread as a minimal smoke-test invocation.
When it happens
Trigger: Invoking build-cost-report.ts with no arguments, or with only non-input flags (e.g. only --trace-project or --out but no --results and no --probe-thread).
Common situations: A developer runs the script expecting a default behavior, or an argument was lost during command construction. Also occurs when --results paths are all behind a shell expansion that produced nothing.
Related errors
- Flag ${arg} needs a value
- --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/931538b3c3d61dc8.
Report an issue: GitHub.