{"record":{"id":"02d1dfeb469f247e","repo":"PaddlePaddle/PaddleOCR","slug":"detection-batch-output-n-string-nout-does-not","errorCode":null,"errorMessage":"Detection batch output N=${String(nOut)} does not match input batch ${String(preps.length)}","messagePattern":"Detection batch output N=(.+?) does not match input batch (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"paddleocr-js/packages/core/src/models/det.ts","lineNumber":434,"sourceCode":"  return new ort.Tensor(\"float32\", out, [1, 1, cropOh, cropOw]);\n}\n\nfunction postprocess(\n  context: DetRunContext,\n  fullOutput: Tensor,\n  preps: DetPreprocessResult[],\n  params: InternalDetParams\n): InternalDetBatchItem[] {\n  const { cv, ort, config } = context;\n  const od = fullOutput.dims;\n  if (od.length !== 3 && od.length !== 4) {\n    throw new Error(`Unexpected det output dims: [${od.join(\", \")}]`);\n  }\n  const ohFull = od.length === 4 ? od[2] : od[1];\n  const owFull = od.length === 4 ? od[3] : od[2];\n  const nOut = od.length === 4 ? od[0] : preps.length === 1 ? 1 : od[0];\n  if (nOut !== preps.length) {\n    throw new Error(\n      `Detection batch output N=${String(nOut)} does not match input batch ${String(preps.length)}`\n    );\n  }\n\n  const maxH = Math.max(...preps.map((p) => p.dstH));\n  const maxW = Math.max(...preps.map((p) => p.dstW));\n\n  const items: InternalDetBatchItem[] = [];\n  for (let i = 0; i < preps.length; i += 1) {\n    const prep = preps[i];\n    const { cropOh, cropOw } = detFeatureCropDims(prep.dstH, prep.dstW, maxH, maxW, ohFull, owFull);\n    const planeTensor = sliceBatchedDetOutputPlane(\n      ort,\n      fullOutput,\n      i,\n      cropOh,\n      cropOw,\n      ohFull,","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr-js/packages/core/src/models/det.ts#L416-L452","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set batchSize (override or default) to the fixed batch size your det model was exported with — usually 1","Re-export the det model with a dynamic first dimension if you need true batching","Check the error message values: N=1 with input batch >1 almost always means fixed-batch-1 model","Use the model assets bundled with the package, which match the runtime batching logic"],"exampleFix":"// before\nconst results = await detModel.predict(cv, mats, { batchSize: 8 }); // model is fixed batch=1\n\n// after\nconst results = await detModel.predict(cv, mats, { batchSize: 1 }); // matches fixed-batch export","handlingStrategy":"validation","validationCode":"// If your det model is fixed batch=1, always pass batchSize 1\nconst detBatchSize = 1; // match the model export\nawait detModel.predict(cv, mats, { batchSize: detBatchSize });","typeGuard":"function matchesFixedBatch(nOut: number, preps: number): boolean {\n  return nOut === preps;\n}","tryCatchPattern":"try { await detModel.predict(cv, mats, { batchSize: 8 }); } catch (e) {\n  if (e instanceof Error && /does not match input batch/.test(e.message)) {\n    await detModel.predict(cv, mats, { batchSize: 1 }); // fixed-batch model\n  } else throw e;\n}","preventionTips":["Check the det model's input dim0 (dynamic vs fixed) before raising batchSize","Default to batchSize 1 unless the model is documented as dynamic-batch","Smoke-test with a batch count that is not a multiple of your batchSize to exercise trailing chunks"],"tags":["paddleocr","onnxruntime","detection","batching","model-mismatch"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}