PaddlePaddle/PaddleOCR · error

Detection batch output N=

Error message

Detection batch output N=${String(nOut)} does not match input batch ${String(preps.length)}

What it means

Thrown by det postprocess() when the batch dimension N of the output tensor does not equal the number of preprocessed inputs. The code derives nOut from the output's first axis (with a batch=1 special case) and requires it to match preps.length. A mismatch means the model was exported with a fixed batch size that disagrees with the runtime batch, or dynamic batching was lost.

Solutions

  1. Set batchSize (override or default) to the fixed batch size your det model was exported with — usually 1
  2. Re-export the det model with a dynamic first dimension if you need true batching
  3. Check the error message values: N=1 with input batch >1 almost always means fixed-batch-1 model
  4. Use the model assets bundled with the package, which match the runtime batching logic

Example fix

// before
const results = await detModel.predict(cv, mats, { batchSize: 8 }); // model is fixed batch=1

// after
const results = await detModel.predict(cv, mats, { batchSize: 1 }); // matches fixed-batch export
Defensive patterns

Strategy: validation

Validate before calling

// If your det model is fixed batch=1, always pass batchSize 1
const detBatchSize = 1; // match the model export
await detModel.predict(cv, mats, { batchSize: detBatchSize });

Type guard

function matchesFixedBatch(nOut: number, preps: number): boolean {
  return nOut === preps;
}

Try / catch

try { await detModel.predict(cv, mats, { batchSize: 8 }); } catch (e) {
  if (e instanceof Error && /does not match input batch/.test(e.message)) {
    await detModel.predict(cv, mats, { batchSize: 1 }); // fixed-batch model
  } else throw e;
}

Prevention

When it happens

Trigger: Running predict() with batchSize > 1 against a det model exported with fixed input batch = 1 (output N=1 while preps.length=4); or a fixed-batch model (N=4) invoked with fewer images because the last chunk is smaller than batchSize.

Common situations: User raises overrides.batchSize / defaultBatchSize for throughput without confirming the ONNX det model has dynamic batch; trailing partial chunk after chunkArray(mats, batchSize) hitting a fixed-N model; model exported with dynamic batch but the code path passing a mismatched tensor.

Related errors


AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14). Data as JSON: /api/errors/02d1dfeb469f247e. Report an issue: GitHub.

Appendix: source

Thrown at paddleocr-js/packages/core/src/models/det.ts:434

  return new ort.Tensor("float32", out, [1, 1, cropOh, cropOw]);
}

function postprocess(
  context: DetRunContext,
  fullOutput: Tensor,
  preps: DetPreprocessResult[],
  params: InternalDetParams
): InternalDetBatchItem[] {
  const { cv, ort, config } = context;
  const od = fullOutput.dims;
  if (od.length !== 3 && od.length !== 4) {
    throw new Error(`Unexpected det output dims: [${od.join(", ")}]`);
  }
  const ohFull = od.length === 4 ? od[2] : od[1];
  const owFull = od.length === 4 ? od[3] : od[2];
  const nOut = od.length === 4 ? od[0] : preps.length === 1 ? 1 : od[0];
  if (nOut !== preps.length) {
    throw new Error(
      `Detection batch output N=${String(nOut)} does not match input batch ${String(preps.length)}`
    );
  }

  const maxH = Math.max(...preps.map((p) => p.dstH));
  const maxW = Math.max(...preps.map((p) => p.dstW));

  const items: InternalDetBatchItem[] = [];
  for (let i = 0; i < preps.length; i += 1) {
    const prep = preps[i];
    const { cropOh, cropOw } = detFeatureCropDims(prep.dstH, prep.dstW, maxH, maxW, ohFull, owFull);
    const planeTensor = sliceBatchedDetOutputPlane(
      ort,
      fullOutput,
      i,
      cropOh,
      cropOw,
      ohFull,

View on GitHub (pinned to 2661c7c0ef)