{"record":{"id":"4becf2ee5a947406","repo":"heygen-com/hyperframes","slug":"onnx-session-is-missing-input-or-output-bindings","errorCode":null,"errorMessage":"ONNX session is missing input or output bindings","messagePattern":"ONNX session is missing input or output bindings","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/background-removal/inference.ts","lineNumber":103,"sourceCode":"    });\n\n  let session: InferenceSession;\n  let providerUsed = choice.label;\n  try {\n    session = await tryCreate(choice.providers);\n  } catch (err) {\n    if (choice.providers[0] === \"cpu\") throw err;\n    options.onProgress?.(\n      `${choice.label} provider failed (${(err as Error).message}); falling back to CPU.`,\n    );\n    session = await tryCreate([\"cpu\"]);\n    providerUsed = \"CPU\";\n  }\n\n  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);","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/background-removal/inference.ts#L85-L121","documentation":"Thrown by createSession when the loaded ONNX InferenceSession has no input or output binding names (session.inputNames[0] or session.outputNames[0] is falsy). The u2net_human_seg model is expected to expose at least one named input and one named output; an empty binding list means the model file is corrupt, truncated, or not a valid ONNX graph. This fires after InferenceSession.create succeeds, so it catches models that load but have a broken graph metadata.","triggerScenarios":"A model file at modelPath(model) that is zero-byte, partially downloaded, a non-ONNX file renamed to .onnx, or an ONNX file whose graph has no named I/O. Triggered inside createSession after the session is constructed.","commonSituations":"A previous ensureModel download was interrupted leaving a truncated file (and the existsSync guard passed because the partial file exists); a user swapped a different model into ~/.cache/hyperframes/…/models/; an ONNX export that omitted I/O names.","solutions":["Delete the cached model and re-download: rm the file under ~/.cache/hyperframes/background-removal/models/ then re-run (ensureModel will re-fetch).","Verify the model file is a valid ONNX graph: load it with Python onnx.load and check graph.input/graph.output.","Confirm the downloaded file size matches the expected ~168 MB; a tiny file indicates truncation.","If supplying a custom model, ensure its graph has named input/output tensors."],"exampleFix":"// before: truncated model in cache\n// createSession() throws: missing input/output bindings\n\n// after\nrm -rf ~/.cache/hyperframes/background-removal/models\n// re-run: ensureModel re-downloads the full u2net_human_seg.onnx","handlingStrategy":"validation","validationCode":"import { existsSync, statSync } from 'node:fs';\nfunction assertModelIntact(path: string, minBytes = 1_000_000): void {\n  if (!existsSync(path)) throw new Error('model missing');\n  if (statSync(path).size < minBytes) throw new Error('model truncated');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await createSession();\n} catch (err) {\n  if (err instanceof Error && err.message.includes('missing input or output bindings')) {\n    await import('node:fs').then(fs => fs.rmSync(modelPath(), { force: true }));\n    await createSession(); // re-downloads\n  }\n}","preventionTips":["After ensureModel, check the file size is ~168 MB to detect truncation.","Delete the cache and re-download if the model is suspect.","Validate custom ONNX models with Python onnx.load before use."],"tags":["onnxruntime","background-removal","model","validation"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}