{"record":{"id":"84c0a68c6cf30314","repo":"heygen-com/hyperframes","slug":"model-did-not-return-output-outputname","errorCode":null,"errorMessage":"Model did not return output '${outputName}'","messagePattern":"Model did not return output '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/background-removal/inference.ts","lineNumber":118,"sourceCode":"  const inputName = session.inputNames[0];\n  const outputName = session.outputNames[0];\n  if (!inputName || !outputName) {\n    throw new Error(\"ONNX session is missing input or output bindings\");\n  }\n\n  // Reused across calls; sized lazily on first frame. Saves ~9 MB/frame at 1080p.\n  const inputData = new Float32Array(3 * INPUT_PLANE);\n  const maskBuf = Buffer.allocUnsafe(INPUT_PLANE);\n  let rgbaBuf: Buffer | null = null;\n  let rgbaBgBuf: Buffer | null = null;\n\n  return {\n    provider: providerUsed,\n    async process(rgb, width, height, withBackground = false) {\n      const tensor = await preprocess(sharp, ort, rgb, width, height, inputData);\n      const outputs = await session.run({ [inputName]: tensor });\n      const output = outputs[outputName];\n      if (!output) throw new Error(`Model did not return output '${outputName}'`);\n      const expectedBytes = width * height * 4;\n      if (!rgbaBuf || rgbaBuf.length !== expectedBytes) {\n        rgbaBuf = Buffer.allocUnsafe(expectedBytes);\n      }\n      if (withBackground) {\n        if (!rgbaBgBuf || rgbaBgBuf.length !== expectedBytes) {\n          rgbaBgBuf = Buffer.allocUnsafe(expectedBytes);\n        }\n      }\n      return await postprocess(\n        sharp,\n        output,\n        rgb,\n        width,\n        height,\n        maskBuf,\n        rgbaBuf,\n        withBackground ? rgbaBgBuf : null,","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/background-removal/inference.ts#L100-L136","documentation":"Thrown per-frame by the session.process closure when session.run returns an outputs map that has no key matching outputName (the first entry from session.outputNames). This means the model executed but produced a different output tensor set than expected — the binding name captured at session creation no longer matches what run() returns. Indicates a model/ONNX-runtime version skew or a model whose output names are non-deterministic across runs (rare). Fires during active rendering, not at session setup.","triggerScenarios":"session.run({ [inputName]: tensor }) resolves with an outputs object whose keys don't include the outputName captured from session.outputNames[0] at creation. Seen when the ONNX runtime version changes between session creation and run, or with a model that dynamically renames outputs.","commonSituations":"An onnxruntime-node upgrade changed output-key semantics; a custom model whose output name varies; memory corruption producing a malformed output map; rendering resumed on a warm process after an onnxruntime hot-reload.","solutions":["Re-create the session (the outputNames are re-read fresh); avoid reusing a session across an onnxruntime reload.","Pin the onnxruntime-node version to the one the package was tested with.","If using a custom model, confirm its output tensor name is stable; log Object.keys(outputs) vs outputName.","Re-download the canonical u2net_human_seg model to rule out a swapped model."],"exampleFix":"// before\nconst session = await createSession({});\n// ... many frames, onnxruntime reloads ...\nsession.process(frame); // throws: output not returned\n\n// after\nconst session = await createSession({});\n// use within a single process lifetime; recreate if onnxruntime reloads","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await session.process(frame, w, h);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('Model did not return output')) {\n    await session.close();\n    session = await createSession(); // recreate, re-read outputNames\n    await session.process(frame, w, h);\n  } else throw err;\n}","preventionTips":["Use a session within a single process lifetime; recreate after any onnxruntime reload.","Pin the onnxruntime-node version to avoid output-key semantics changes.","Log Object.keys(outputs) vs outputName when debugging."],"tags":["onnxruntime","background-removal","model","runtime"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}