{"record":{"id":"10c95718eb9df17e","repo":"different-ai/openwork","slug":"no-output-from-cua-model","errorCode":null,"errorMessage":"No output from CUA model.","messagePattern":"No output from CUA model\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/handsfree/src/cua-runner.mjs","lineNumber":41,"sourceCode":"  for (let turn = 0; turn < maxTurns; turn += 1) {\n    if (signal?.aborted) return { ok: true, messages, turns: turn, aborted: true };\n    onProgress?.({ kind: \"turn\", turn: turn + 1 });\n\n    const response = await fetch(\"https://api.openai.com/v1/responses\", {\n      method: \"POST\",\n      headers: { Authorization: `Bearer ${apiKey}`, \"Content-Type\": \"application/json\" },\n      body: JSON.stringify({ model, input: items, tools: [{ type: \"computer\" }] }),\n      signal,\n    });\n\n    if (!response.ok) {\n      const errorText = await response.text().catch(() => \"\");\n      throw new Error(`CUA API error ${response.status}: ${errorText.slice(0, 300)}`);\n    }\n\n    const result = await response.json();\n    const output = result.output || [];\n    if (!output.length) throw new Error(\"No output from CUA model.\");\n    items.push(...output);\n\n    let computerCall = null;\n    for (const item of output) {\n      if (item.type === \"message\") {\n        const text = item.content?.map((part) => part.text || \"\").join(\"\") || \"\";\n        if (text) {\n          messages.push(text);\n          onProgress?.({ kind: \"message\", text });\n        }\n      }\n      if (item.type === \"computer_call\") computerCall = item;\n    }\n\n    if (!computerCall) return { ok: true, messages, turns: turn + 1 };\n\n    for (const action of computerCall.actions || (computerCall.action ? [computerCall.action] : [])) {\n      if (signal?.aborted) return { ok: true, messages, turns: turn + 1, aborted: true };","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/packages/handsfree/src/cua-runner.mjs#L23-L59","documentation":"The OpenAI Responses API returned HTTP 200 but result.output was empty, so the loop has nothing to process — no message, no computer_call. The library treats a zero-length output array as a protocol failure rather than silently continuing, since the CUA loop cannot advance without model output.","triggerScenarios":"result.output || [] is empty: the API succeeded but produced no items (e.g. incomplete response, response truncated by the server, an unexpected response shape where output is missing/null, or the model returned only fields the code ignores).","commonSituations":"OpenAI changes/returns a shape where output items live elsewhere; a model that doesn't support the computer tool returning an empty completion; max_output_tokens set too low elsewhere; intermittent server bug returning 200 with empty body.","solutions":["Log result.output and result.status — if status is 'incomplete', inspect result.incomplete_details for the reason.","Retry the turn; a single empty output is often transient.","Confirm the model name supports computer-use preview tools; switch to a supported computer-use model.","If OpenAI changed the response shape, update the runner to read the new field (check API changelog)."],"exampleFix":"// before\nif (!output.length) throw new Error(\"No output from CUA model.\");\n// after\nif (!output.length && result.status !== \"incomplete\") throw new Error(\"No output from CUA model.\");","handlingStrategy":"retry","validationCode":null,"typeGuard":"function hasOutput(r: unknown): r is { output: unknown[] } {\n  return typeof r === \"object\" && r !== null && Array.isArray((r as { output?: unknown }).output) && (r as { output: unknown[] }).output.length > 0;\n}","tryCatchPattern":"try {\n  await runCuaLoop(opts);\n} catch (e) {\n  if (e.message === \"No output from CUA model.\") {\n    // retry the turn once, then surface result.status/incomplete_details\n  } else throw e;\n}","preventionTips":["Log the full API response on failure for postmortems","Use supported computer-use models only","Set reasonable max_output_tokens so responses are never empty"],"tags":["api","openai","empty-response","protocol"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}