{"record":{"id":"e3ea3a10a0f14e14","repo":"can1357/oh-my-pi","slug":"gpt-5-harmony-leak-recurred-after-truncate-and-res","errorCode":null,"errorMessage":"GPT-5 Harmony leak recurred after truncate-and-resume recovery (${signalListLabel(err.detection.signals)}).","messagePattern":"GPT-5 Harmony leak recurred after truncate-and-resume recovery \\((.+?)\\)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/agent-loop.ts","lineNumber":1274,"sourceCode":"\t\t\t\t\t\tsignal,\n\t\t\t\t\t\tstream,\n\t\t\t\t\t\ttelemetry,\n\t\t\t\t\t\tinvokeAgentSpan,\n\t\t\t\t\t\tstepCounter,\n\t\t\t\t\t\tstreamFn,\n\t\t\t\t\t\tharmonyRetryAttempt,\n\t\t\t\t\t\thostToolChoice,\n\t\t\t\t\t\tsoftRequirementState.forcedToolChoice,\n\t\t\t\t\t\tpreparedProviderCall,\n\t\t\t\t\t);\n\t\t\t\t\tharmonyRetryAttempt = 0;\n\t\t\t\t\tharmonyTruncateResumeCount = 0;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (!(err instanceof HarmonyLeakInterruption)) throw err;\n\t\t\t\t\tif (err.recovered) {\n\t\t\t\t\t\tif (harmonyTruncateResumeCount >= 2) {\n\t\t\t\t\t\t\tawait emitHarmonyAudit(config, err, \"escalated\", harmonyRetryAttempt);\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`GPT-5 Harmony leak recurred after truncate-and-resume recovery (${signalListLabel(err.detection.signals)}).`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tharmonyTruncateResumeCount++;\n\t\t\t\t\t\trecovered = err.recovered;\n\t\t\t\t\t\tmessage = recovered.message;\n\t\t\t\t\t\tawait emitHarmonyAudit(config, err, \"truncate_resume\", harmonyRetryAttempt);\n\t\t\t\t\t\t// A recovered message completes the turn, so the abort-retry counter\n\t\t\t\t\t\t// resets like the normal success path (the truncate-resume counter\n\t\t\t\t\t\t// keeps accumulating for its cross-turn cap).\n\t\t\t\t\t\tharmonyRetryAttempt = 0;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (harmonyRetryAttempt >= 2) {\n\t\t\t\t\t\t\tawait emitHarmonyAudit(config, err, \"escalated\", harmonyRetryAttempt);\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`GPT-5 Harmony leak persisted after ${harmonyRetryAttempt} retries (${signalListLabel(err.detection.signals)}).`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}","sourceCodeStart":1256,"sourceCodeEnd":1292,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/agent/src/agent-loop.ts#L1256-L1292","documentation":"When the GPT-5 model leaks Harmony-format markup into its output, the agent loop attempts a truncate-and-resume recovery (replacing the leaked assistant message and resuming). This error is thrown after that recovery has succeeded twice already within the window (harmonyTruncateResumeCount >= 2): the leak keeps recurring, so the loop escalates instead of continuing to paper over it. The message lists the detection signals that identified the leak.","triggerScenarios":"Streaming an assistant response from a GPT-5-class model where HarmonyLeakInterruption with recovered=true is raised on the third occurrence within the cap — i.e. the model repeatedly emits Harmony tokens (<|start|>, channel markers, etc.) even after two truncate-and-resume recoveries.","commonSituations":"A specific model snapshot/revision regressed into emitting its internal chat template; aggressive system prompts or few-shot content that triggers template echo; misrouted model IDs hitting a Harmony-trained model without the provider-side template stripping.","solutions":["Switch to a different model or model snapshot that does not leak Harmony tokens.","Review/adjust the system prompt for content that induces the model to echo its chat template.","If this is a provider-side regression, report it; meanwhile pin a known-good model revision via the catalog config.","Temporarily raise the truncate-resume cap only if continued degraded output is preferable to failing the turn."],"exampleFix":"// before\nconst agent = createAgent({ model: \"gpt-5-preview-0902\" });\n// after\nconst agent = createAgent({ model: \"gpt-5\" }); // known-good revision; or catch and fall back:\ntry {\n  await runAgent(agent);\n} catch (err) {\n  if (String(err).includes(\"Harmony leak recurred\")) await runAgent(fallbackAgent);\n  else throw err;\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"function isHarmonyLeakEscalation(err: unknown): err is Error {\n  return err instanceof Error && err.message.includes(\"Harmony leak recurred after truncate-and-resume\");\n}","tryCatchPattern":"try {\n  await runTurn();\n} catch (err) {\n  if (isHarmonyLeakEscalation(err)) {\n    await runTurn({ model: fallbackModel }); // retry with a non-leaking model\n  } else {\n    throw err;\n  }\n}","preventionTips":["Pin a model revision known not to leak Harmony tokens.","Monitor harmony audit events ('truncate_resume' emissions) as an early signal before escalation.","Avoid prompt content that induces template echo in GPT-5-class models.","Configure a fallback model for automatic recovery on escalation."],"tags":["gpt-5","harmony-leak","model-output","recovery-exhausted"],"backgroundTag":"harmony-leak-escalation","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}