{"record":{"id":"7c466cfd26fa7ee8","repo":"can1357/oh-my-pi","slug":"handoff-generation-produced-no-content","errorCode":null,"errorMessage":"Handoff generation produced no content","messagePattern":"Handoff generation produced no content","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/session/session-handoff.ts","lineNumber":206,"sourceCode":"\t\t\tconst handoffText = this.#host.deobfuscateFromProvider(rawHandoffText);\n\n\t\t\tthrowIfHandoffAborted(handoffSignal);\n\t\t\tif (!handoffText || handoffText.trim().length === 0) {\n\t\t\t\t// Empty/whitespace-only generation is a real failure, not a user\n\t\t\t\t// cancellation. #7904 stopped masking provider errors as \"Handoff\n\t\t\t\t// cancelled\"; an empty document is the remaining path that produced the\n\t\t\t\t// same misleading, undebuggable message (#7993).\n\t\t\t\tlogger.warn(\"Handoff generation produced no content\", {\n\t\t\t\t\tsessionId: this.#host.sessionId(),\n\t\t\t\t\tautoTriggered: options?.autoTriggered ?? false,\n\t\t\t\t});\n\t\t\t\t// Auto-handoff is best-effort: returning undefined lets maintenance fall\n\t\t\t\t// back to the next compaction method. A user-initiated handoff must\n\t\t\t\t// surface the failure instead of a silent, misleading \"cancelled\".\n\t\t\t\tif (options?.autoTriggered) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tthrow new Error(\"Handoff generation produced no content\");\n\t\t\t}\n\n\t\t\tlet savedPath: string | undefined;\n\t\t\tif (options?.autoTriggered && this.#host.settings.get(\"compaction.handoffSaveToDisk\")) {\n\t\t\t\tconst artifactsDir = this.#host.sessionManager.getArtifactsDir();\n\t\t\t\tif (artifactsDir) {\n\t\t\t\t\tconst handoffFilePath = path.join(artifactsDir, createHandoffFileName());\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait Bun.write(handoffFilePath, `${handoffText}\\n`);\n\t\t\t\t\t\tsavedPath = handoffFilePath;\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger.warn(\"Failed to save handoff document to disk\", {\n\t\t\t\t\t\t\tpath: handoffFilePath,\n\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlogger.debug(\"Skipping handoff document save because session is not persisted\");","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/session/session-handoff.ts#L188-L224","documentation":"generateDocument treats an empty generation as a hard failure when the handoff was user-initiated: if the LLM turn completes without producing content, it throws instead of silently returning. For autoTriggered handoffs it instead returns undefined so maintenance can fall back to the next compaction method — the throw exists to avoid a misleading 'cancelled' result on explicit requests.","triggerScenarios":"generateDocument (options.autoTriggered falsy) where the handoff LLM response contains no usable content (empty stream, model returned nothing, response filtered).","commonSituations":"Provider returned an empty/blocked response; max-tokens set too low; upstream API error swallowed into an empty result; model produced only tool calls with no text.","solutions":["Retry the handoff generation, possibly with a different model or higher output limit","Check provider logs/response for blocked or empty completions and fix the request (prompt, maxTokens)","Switch to a non-handoff compaction method (e.g. summarize) as the fallback","Catch the error for user-initiated compaction and surface a retry option"],"exampleFix":"// before\nawait handoff.generateDocument(signal); // throws on empty output\n// after\ntry {\n  await handoff.generateDocument(signal);\n} catch (err) {\n  if (err.message === \"Handoff generation produced no content\") {\n    await session.compact(); // fallback method\n    return;\n  }\n  throw err;\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await handoff.generateDocument(signal);\n} catch (err) {\n  if (err instanceof Error && err.message === \"Handoff generation produced no content\") {\n    await session.compact({ method: \"summarize\" }); // alternative compaction\n    return;\n  }\n  throw err;\n}","preventionTips":["Set adequate max output tokens for the handoff generation","Retry once with a different model on empty responses","Prefer auto-triggered handoff (returns undefined) where fallback is acceptable","Monitor provider-side blocks/filters that produce empty completions"],"tags":["empty-response","llm","handoff","compaction"],"backgroundTag":"empty-llm-response","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}