Egonex-AI/Understand-Anything · error · Error

Batch artifact does not match the required shape

Error message

Batch artifact does not match the required shape

What it means

Thrown by validateBatchArtifact when batches.json (the output of the batching worker) does not satisfy the contract the benchmark needs to size agent input. It enforces schemaVersion===1, a non-empty algorithm string, a batches array whose length equals totalBatches, and a per-batch shape of {batchIndex, files[], batchImportData, neighborMap}. This is a hard gate because the agent-input byte estimate (JSON.stringify of files+batchImportData+neighborMap) is computed unconditionally right after this check.

Source

Thrown at scripts/lib/large-repo-benchmark.mjs:771

function validateBatchArtifact(batches) {
  if (
    !isRecord(batches) ||
    batches.schemaVersion !== 1 ||
    typeof batches.algorithm !== 'string' ||
    batches.algorithm.length === 0 ||
    !Array.isArray(batches.batches) ||
    !isNonNegativeInteger(batches.totalBatches) ||
    batches.totalBatches !== batches.batches.length ||
    batches.batches.some(
      (batch) =>
        !isRecord(batch) ||
        !isNonNegativeInteger(batch.batchIndex) ||
        !Array.isArray(batch.files) ||
        !isRecord(batch.batchImportData) ||
        !isRecord(batch.neighborMap),
    )
  ) {
    throw new Error('Batch artifact does not match the required shape');
  }
}

function markArtifactFailure(stage, stageName, error, redactionRoots) {
  const rawMessage = error instanceof Error ? error.message : String(error);
  const safeMessage = sanitizeBounded(
    `${stageName} stage produced an invalid artifact: ${rawMessage}`,
    redactionRoots,
  );
  stage.status = 'failed';
  stage.stderr = safeMessage.text;
  stage.stderrTruncated ||= safeMessage.truncated;
}

function fileSizeOrZero(path) {
  try {
    return statSync(path).size;
  } catch {

View on GitHub (pinned to 32944829e7)

Solutions

  1. Open artifactRoot/batches.json and confirm schemaVersion===1, a non-empty algorithm string, and totalBatches === batches.length.
  2. Re-run the batching stage on its prior inputs (scan-result-with-imports.json) and inspect stderr; a crash there usually leaves totalBatches unset.
  3. If you swapped in a different batching algorithm, ensure it still emits schemaVersion:1 and the four required per-batch fields.
  4. Delete batches.json and the artifactRoot intermediate so the benchmark regenerates it from the validated scan+import artifacts.
  5. Verify the import stage (error 20) passed — batching depends on batchImportData/neighborMap produced upstream, and a skipped import stage yields empty maps that some custom batchers may omit.

Example fix

// before: batcher emits arrays without the envelope
{ "batches": [ { "files": ["a.ts"] } ] }

// after: full validated shape
{
  "schemaVersion": 1,
  "algorithm": "greedy-import-locality",
  "totalBatches": 1,
  "batches": [
    { "batchIndex": 0, "files": ["a.ts"], "batchImportData": {}, "neighborMap": {} }
  ]
}
Defensive patterns

Strategy: validation

Validate before calling

function isValidBatchArtifact(v) {
  if (typeof v !== 'object' || v === null) return false;
  if (v.schemaVersion !== 1) return false;
  if (typeof v.algorithm !== 'string' || v.algorithm.length === 0) return false;
  if (!Array.isArray(v.batches)) return false;
  if (!Number.isInteger(v.totalBatches) || v.totalBatches !== v.batches.length) return false;
  for (const b of v.batches) {
    if (typeof b !== 'object' || b === null) return false;
    if (!Number.isInteger(b.batchIndex) || b.batchIndex < 0) return false;
    if (!Array.isArray(b.files)) return false;
    if (typeof b.batchImportData !== 'object' || b.batchImportData === null) return false;
    if (typeof b.neighborMap !== 'object' || b.neighborMap === null) return false;
  }
  return true;
}

Type guard

function isBatchArtifact(v) {
  if (typeof v !== 'object' || v === null) return false;
  const o = v;
  return o.schemaVersion === 1
    && typeof o.algorithm === 'string' && o.algorithm.length > 0
    && Array.isArray(o.batches)
    && Number.isInteger(o.totalBatches) && o.totalBatches === o.batches.length
    && o.batches.every((b) =>
        b !== null && typeof b === 'object'
        && Number.isInteger(b.batchIndex) && b.batchIndex >= 0
        && Array.isArray(b.files)
        && typeof b.batchImportData === 'object' && b.batchImportData !== null
        && typeof b.neighborMap === 'object' && b.neighborMap !== null);
}

Try / catch

try {
  validateBatchArtifact(batches);
} catch (e) {
  console.error('batches.json shape invalid:', e.message, batchesPath);
  throw e;
}

Prevention

When it happens

Trigger: The benchmark reads artifactRoot/batches.json after batchStage.status === 'ok' and calls validateBatchArtifact(batches). Throws when schemaVersion !== 1, algorithm is missing/empty/non-string, batches is not an array, totalBatches !== batches.length, or any batch is missing batchIndex (non-negative int), files (array), batchImportData (record), or neighborMap (record).

Common situations: A custom or out-of-date batching implementation that omits schemaVersion or the algorithm tag. A partial write where totalBatches was updated but batches truncated (interrupted write / OOM kill mid-stream). A neighborMap that came back null from a worker that skipped import enrichment. Editing batches.json by hand and forgetting the totalBatches counter.

Related errors


AI-assisted analysis of Egonex-AI/Understand-Anything@32944829e7 (2026-08-12). Data as JSON: /api/errors/c85ce0e2f8d9f13d. Report an issue: GitHub.