{"record":{"id":"b69a1c7f790d963d","repo":"can1357/oh-my-pi","slug":"gpt-5-harmony-leak-persisted-after-harmonyretrya","errorCode":null,"errorMessage":"GPT-5 Harmony leak persisted after ${harmonyRetryAttempt} retries (${signalListLabel(err.detection.signals)}).","messagePattern":"GPT-5 Harmony leak persisted after (.+?) retries \\((.+?)\\)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/agent-loop.ts","lineNumber":1289,"sourceCode":"\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}\n\t\t\t\t\t\tawait emitHarmonyAudit(config, err, \"abort_retry\", harmonyRetryAttempt);\n\t\t\t\t\t\tharmonyRetryAttempt++;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (recovered) {\n\t\t\t\t\tmessage = snapshotAssistantMessage(message);\n\t\t\t\t\tcurrentContext.messages.push(message);\n\t\t\t\t\tstream.push({ type: \"message_start\", message: snapshotAssistantMessage(message) });\n\t\t\t\t\tstream.push({ type: \"message_end\", message: snapshotAssistantMessage(message) });\n\t\t\t\t}\n\t\t\t\tnewMessages.push(message);\n\n\t\t\t\t// The escalation choice (if any) applied to the call above; clear it so\n\t\t\t\t// only the single escalation turn carries the forced choice.","sourceCodeStart":1271,"sourceCodeEnd":1307,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/agent/src/agent-loop.ts#L1271-L1307","documentation":"The agent loop detects GPT-5 'Harmony' template leaks (raw harmony channel tokens like <|channel|> appearing in model output). It first tries abort-and-retry (up to 2 times) and truncate-and-resume recovery; if the leak still persists after the retry budget is exhausted, the loop throws this error instead of letting corrupted assistant output through. It is a deliberate escalation so callers fail loudly rather than consume leaked internal-format text.","triggerScenarios":"A streaming model response raises HarmonyLeakInterruption with recovered=false, and harmonyRetryAttempt is already >= 2 — i.e. three consecutive model responses from a GPT-5 harmony-dialect model leaked harmony control tokens and neither in-stream truncation nor re-issuing the request cleaned them up.","commonSituations":"Running GPT-5/gpt-5-codex-class models via a provider or proxy that mangles the harmony chat template (wrong dialect routing, custom base URL, patched sampler); very long contexts or unusual system prompts that push the model into emitting raw channel markers; provider-side incidents where the harmony serialization changes.","solutions":["Retry the request later or switch to a different model/endpoint — repeated leaks usually indicate a provider-side regression, not a bug in your code","Verify the model is being served through the correct harmony-dialect route (check PI_DIALECT / provider routing config); a non-harmony endpoint serving a harmony model leaks tokens","Clear or shorten the conversation (compact/truncate history) — long or adversarial contexts increase leak probability","Check provider status/changelog for a harmony template change and pin a known-good model revision"],"exampleFix":"// before: same corrupted session retried manually, still fails\nawait agent.prompt(\"continue\"); // throws: Harmony leak persisted after 2 retries\n// after: switch model or start a fresh session\nagent.setModel(\"claude-opus-4\"); // or agent.newSession() to drop the poisoned context\nawait agent.prompt(\"continue\");","handlingStrategy":"retry","validationCode":"// Check model routing before starting a harmony-sensitive session\nconst model = agent.getModel();\nif (model && /gpt-5/i.test(model.id) && Bun.env.PI_DIALECT !== \"harmony\") {\n  console.warn(\"gpt-5 model without harmony dialect routing: leak risk\");\n}","typeGuard":"function isHarmonyLeakError(err: unknown): err is Error & { message: string } {\n  return err instanceof Error && err.message.includes(\"Harmony leak persisted\");\n}","tryCatchPattern":"try {\n  await agent.prompt(userInput);\n} catch (err) {\n  if (isHarmonyLeakError(err)) {\n    // provider-side serialization problem: do NOT retry in a tight loop\n    logger.error(\"harmony leak persisted\", { signals: err.message });\n    await compactOrRestartSession(agent); // drop poisoned context / switch model\n  } else throw err;\n}","preventionTips":["Route harmony-family models through dialect-correct endpoints (check PI_DIALECT and provider config)","Pin known-good model revisions and watch provider status pages for template regressions","Compact long sessions proactively — leak probability grows with context size","Audit harmony audit events (emitHarmonyAudit output) to catch truncate_resume warnings before they escalate"],"tags":["llm","gpt-5","harmony","retry-exhausted","model-output"],"backgroundTag":"harmony-template-leak","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}