lobehub/lobehub · error · InvalidArgumentError

Expected a JSON array of result items (or { items: [...] })

Error message

Expected a JSON array of result items (or { items: [...] })

What it means

Thrown during eval batch result reporting when the parsed JSON from the input file or stdin is neither a top-level JSON array nor an object with an 'items' array — or when the resulting array is empty. The batch report command expects a non-empty list of result items; a single object, a non-array value, or an empty array are all rejected before the server mutation.

Source

Thrown at apps/cli/src/commands/eval.ts:999

    .option('--json', 'Output JSON envelope')
    .action(async (options: JsonOption & { file: string; runId: string }) =>
      executeCommand(
        options,
        async () => {
          const raw =
            options.file === '-'
              ? await new Promise<string>((resolve, reject) => {
                  let data = '';
                  process.stdin.on('data', (chunk) => (data += chunk));
                  process.stdin.on('end', () => resolve(data));
                  process.stdin.on('error', reject);
                })
              : await readFile(options.file, 'utf8');

          const parsed = JSON.parse(raw);
          const items = Array.isArray(parsed) ? parsed : parsed.items;
          if (!Array.isArray(items) || items.length === 0) {
            throw new InvalidArgumentError(
              'Expected a JSON array of result items (or { items: [...] })',
            );
          }

          const client = await getTrpcClient();
          return client.agentEvalExternal.reportResultsBatch.mutate({
            items,
            runId: options.runId,
          } as any);
        },
        `Reported batch results for run ${pc.bold(options.runId)}`,
      ),
    );

  // ============================================
  // Eval Thread Operations (external eval API)
  // ============================================
  evalCmd

View on GitHub (pinned to 10f24d7ade)

Solutions

  1. Ensure the file contains a JSON array: [{...}, {...}] or an object with an items array: {"items":[{...}]}.
  2. Verify the array is non-empty — at least one result item is required.
  3. If wrapping in an object, use the exact key 'items': {"items":[...]}.
  4. Validate the structure: jq 'if type=="array" then length else .items|length end' file.json should be > 0.
  5. If using stdin (--file -), ensure the pipe actually produces output: cat results.json | lh eval report-batch --file - --run-id run-1.

Example fix

// before (single object, not an array):
// results.json:
{ "caseId": "c1", "status": "pass" }
// after (array of items):
// results.json:
[{ "caseId": "c1", "status": "pass" }]
// or (items wrapper):
{ "items": [{ "caseId": "c1", "status": "pass" }] }
Defensive patterns

Strategy: validation

Validate before calling

import { readFile } from 'node:fs/promises';

function validateBatchItems(raw: string): unknown[] {
  const parsed = JSON.parse(raw);
  const items = Array.isArray(parsed) ? parsed : parsed.items;
  if (!Array.isArray(items) || items.length === 0) {
    throw new Error('Expected a JSON array of result items (or { items: [...] })');
  }
  return items;
}
// Usage: const items = validateBatchItems(await readFile('results.json', 'utf8'));

Type guard

function isBatchPayload(value: unknown): value is unknown[] | { items: unknown[] } {
  if (Array.isArray(value)) return true;
  return typeof value === 'object' && value !== null && Array.isArray((value as any).items);
}

Prevention

When it happens

Trigger: Running lh eval report-batch --file <path> --run-id <id> where the file (or stdin) contains: a single JSON object (not wrapped in an array or {items:[...]}), an empty array '[]', an object without an 'items' key, or an object where items is not an array. Also fires when piping an empty or malformed payload via --file -.

Common situations: 1) File contains a single result object instead of an array of results. 2) Empty file or empty array. 3) File has a different wrapper key (e.g. {results:[...]} instead of {items:[...]}). 4) Stdin pipe produced no data or invalid JSON. 5) JSON.parse itself succeeded but the structure is wrong.

Related errors


AI-assisted analysis of lobehub/lobehub@10f24d7ade (2026-08-12). Data as JSON: /api/errors/5013d7222ef36c0d. Report an issue: GitHub.