vercel-labs/agent-skills · error · Error

signals.json is missing schemaVersion; pass collect-signals

Error message

signals.json is missing schemaVersion; pass collect-signals output as the first file.

What it means

Thrown by mergeSignals() when the first `signals` argument has no `schemaVersion` field. collect-signals.mjs always emits a `schemaVersion` at the top of its output object, so its absence means the first file is not collect-signals output — typically the two input files were passed in the wrong order. The guard prevents merging a codebase scan as if it were metrics signals.

Source

Thrown at skills/vercel-optimize/scripts/merge-signals.mjs:42

    readJson(args.codebasePath, 'codebase scan'),
  ]);

  const merged = mergeSignals(signals, codebase);
  const body = JSON.stringify(merged, null, 2) + '\n';
  if (args.outPath) {
    await writeOutput(args.outPath, body, { force: args.force });
    log(`wrote ${args.outPath}`);
  } else {
    process.stdout.write(body);
  }
}

export function mergeSignals(signals, codebase) {
  assertObject(signals, 'signals');
  assertObject(codebase, 'codebase scan');

  if (!signals.schemaVersion) {
    throw new Error('signals.json is missing schemaVersion; pass collect-signals output as the first file.');
  }
  if (!Array.isArray(codebase.routes) || !Array.isArray(codebase.findings) || !codebase.stack) {
    throw new Error('codebase.json must be scan-codebase output with stack, routes[], and findings[].');
  }

  return {
    ...signals,
    codebase: annotateCodebaseScan(signals, codebase),
  };
}

export function annotateCodebaseScan(signals, codebase) {
  const index = buildRouteMetricIndex(signals);
  return {
    ...codebase,
    findings: (codebase.findings ?? []).map((finding) => annotateFinding(finding, index)),
  };
}

View on GitHub (pinned to b8caa260a4)

Solutions

  1. Pass files in the correct order: `merge-signals.mjs <signals.json> <codebase.json>` — collect-signals output first.
  2. Re-run collect-signals to regenerate a complete signals.json that includes schemaVersion.
  3. If merging manually via mergeSignals(), ensure the first argument is the object from collect-signals.

Example fix

# before (wrong order)
$ node scripts/merge-signals.mjs codebase.json signals.json -o merged.json
-> signals.json is missing schemaVersion

# after (correct order)
$ node scripts/merge-signals.mjs signals.json codebase.json -o merged.json
Defensive patterns

Strategy: type-guard

Validate before calling

import { readFileSync } from 'node:fs';
function loadSignals(path) {
  const s = JSON.parse(readFileSync(path, 'utf-8'));
  if (!s.schemaVersion) throw new Error(`${path} is not collect-signals output (missing schemaVersion)`);
  return s;
}
const signals = loadSignals(process.argv[2]);

Type guard

function isCollectSignalsOutput(v) {
  return v !== null && typeof v === 'object' && !Array.isArray(v) && typeof v.schemaVersion !== 'undefined';
}

Prevention

When it happens

Trigger: Calling merge-signals with codebase.json first and signals.json second; passing a hand-written or partial JSON that lacks schemaVersion; passing an older/different collector output that never had the field.

Common situations: Argument order swapped on the command line; a wrapper script feeding files in the wrong order; an out-of-date collect-signals run predating the schemaVersion field.

Related errors


AI-assisted analysis of vercel-labs/agent-skills@b8caa260a4 (2026-08-13). Data as JSON: /api/errors/1908da47abce70e7. Report an issue: GitHub.