Summary
Assistant messages with mode: "compaction" persist their reasoning parts including metadata.openai.reasoningEncryptedContent. Those parts are then replayed in every subsequent request on the main chain.
The compaction turn is a separate, uncached one-off call (tokens.cache.read: 0), and its encrypted reasoning blobs are bound to a different continuation identity than every other response in the session. Azure Foundry's Responses endpoint rejects the mixed input array:
HTTP 400 invalid_request_error param: input code: invalid_value
Conflicting authenticated continuation identities.
The error is isRetryable: false, so the session is permanently dead: every prompt fails in ~5s. /compact cannot rescue it either, because the compaction request itself replays the poisoned items.
Environment
- opencode: 1.18.30 (session originally created under 1.18.20)
- OS: macOS 26.6.2, arm64
- Install: Homebrew
- Provider: custom
openai-foundry, npm: @ai-sdk/openai, Azure Foundry Responses endpoint behind an internal gateway (/openai/v1/responses)
- Model:
gpt-5.6-sol, variant xhigh — same model/provider/variant for the whole session, no model switching
Reproduction
- Run a long session against an Azure Foundry Responses-API provider.
- Let auto-compaction fire. It produces an assistant message with
mode: "compaction", agent: "compaction", summary: true, carrying both a text part (the summary) and several reasoning parts with reasoningEncryptedContent.
- Continue the session past the compaction point.
- Every subsequent request replays the compaction message's reasoning items alongside the main chain's →
400 Conflicting authenticated continuation identities.
In my case the compaction fired on 09-09; the endpoint began enforcing the identity check around 09-10 08:00 UTC, and the session died at that point with no user-visible cause.
Evidence
I extracted the stored reasoning items from the affected session and replayed them directly against the endpoint. The input array held the post-compaction reasoning items plus a trivial "say ok" user message.
| input |
result |
| all 581 post-compaction items |
CONFLICT (3/3 runs) |
| same 581 minus the compaction message's 3 items |
OK (3/3 runs) |
| the compaction message's 3 items alone |
OK |
| any one compaction item + any one later item |
CONFLICT |
| one pre-compaction item + one latest item |
OK |
Binary search over the prefix converged on the first post-compaction non-compaction item as the first to collide — i.e. the compaction message's items are incompatible with everything that follows, and self-consistent among themselves.
Deleting just those 3 reasoning parts via DELETE /session/{id}/message/{id}/part/{id}, leaving the 4212-char summary text part intact, makes the full stored history replay cleanly. Confirmed end-to-end: after the deletion the session resumed and streams normally, with no loss of context.
A second session on the same machine corroborates the mechanism: it died on 09-10 08:17 from its 09-09 compaction message, then a new compaction on 09-10 11:30 pushed the poisoned item out of the replay window and it resumed working. It now carries 2 fresh encrypted reasoning parts on the new compaction message — the same latent failure.
Suggested fix
1. Don't persist encrypted reasoning on compaction messages. Only the summary text is ever needed from a mode: "compaction" turn. Dropping reasoningEncryptedContent / itemId for those messages removes the root cause and costs nothing.
2. Add this error to the stale-reasoning classifier. The open PRs #48908 and #48918 add a recovery path (strip crypto tokens, retry once) keyed on:
encrypted_content was not issued to this caller
invalid_encrypted_content
Referenced reasoning item '...' was not found or has expired
Conflicting authenticated continuation identities. is a distinct Azure-side string and would not be matched, so those PRs leave this case bricked. It has the same shape (400 / invalid_request_error / param: input) and the same remedy.
Fix 1 alone resolves this report. Fix 2 is worth having regardless, since it also covers identity divergence from any other source.
Related
Same family: caller-bound reasoning state persisted and replayed. This one is distinguished by the poisoned item being generated by opencode's own compaction agent rather than by an external change (restart, idle, model switch), which is why it is both reproducible and permanent.
Workaround
Delete the reasoning parts on the compaction message, keeping its text part:
DELETE /session/{sessionID}/message/{compactionMessageID}/part/{reasoningPartID}
Gateway hostname and request IDs redacted; happy to supply Azure apim-request-id / x-request-id values privately for upstream triage.
Summary
Assistant messages with
mode: "compaction"persist theirreasoningparts includingmetadata.openai.reasoningEncryptedContent. Those parts are then replayed in every subsequent request on the main chain.The compaction turn is a separate, uncached one-off call (
tokens.cache.read: 0), and its encrypted reasoning blobs are bound to a different continuation identity than every other response in the session. Azure Foundry's Responses endpoint rejects the mixedinputarray:The error is
isRetryable: false, so the session is permanently dead: every prompt fails in ~5s./compactcannot rescue it either, because the compaction request itself replays the poisoned items.Environment
openai-foundry,npm: @ai-sdk/openai, Azure Foundry Responses endpoint behind an internal gateway (/openai/v1/responses)gpt-5.6-sol, variantxhigh— same model/provider/variant for the whole session, no model switchingReproduction
mode: "compaction",agent: "compaction",summary: true, carrying both atextpart (the summary) and severalreasoningparts withreasoningEncryptedContent.400 Conflicting authenticated continuation identities.In my case the compaction fired on 09-09; the endpoint began enforcing the identity check around 09-10 08:00 UTC, and the session died at that point with no user-visible cause.
Evidence
I extracted the stored reasoning items from the affected session and replayed them directly against the endpoint. The
inputarray held the post-compaction reasoning items plus a trivial"say ok"user message.Binary search over the prefix converged on the first post-compaction non-compaction item as the first to collide — i.e. the compaction message's items are incompatible with everything that follows, and self-consistent among themselves.
Deleting just those 3
reasoningparts viaDELETE /session/{id}/message/{id}/part/{id}, leaving the 4212-char summarytextpart intact, makes the full stored history replay cleanly. Confirmed end-to-end: after the deletion the session resumed and streams normally, with no loss of context.A second session on the same machine corroborates the mechanism: it died on 09-10 08:17 from its 09-09 compaction message, then a new compaction on 09-10 11:30 pushed the poisoned item out of the replay window and it resumed working. It now carries 2 fresh encrypted reasoning parts on the new compaction message — the same latent failure.
Suggested fix
1. Don't persist encrypted reasoning on compaction messages. Only the summary
textis ever needed from amode: "compaction"turn. DroppingreasoningEncryptedContent/itemIdfor those messages removes the root cause and costs nothing.2. Add this error to the
stale-reasoningclassifier. The open PRs #48908 and #48918 add a recovery path (strip crypto tokens, retry once) keyed on:encrypted_contentwas not issued to this callerinvalid_encrypted_contentReferenced reasoning item '...' was not found or has expiredConflicting authenticated continuation identities.is a distinct Azure-side string and would not be matched, so those PRs leave this case bricked. It has the same shape (400 / invalid_request_error / param: input) and the same remedy.Fix 1 alone resolves this report. Fix 2 is worth having regardless, since it also covers identity divergence from any other source.
Related
Same family: caller-bound reasoning state persisted and replayed. This one is distinguished by the poisoned item being generated by opencode's own compaction agent rather than by an external change (restart, idle, model switch), which is why it is both reproducible and permanent.
Workaround
Delete the
reasoningparts on the compaction message, keeping itstextpart:Gateway hostname and request IDs redacted; happy to supply Azure
apim-request-id/x-request-idvalues privately for upstream triage.