Description
When using the GitHub Copilot provider with gpt-5.5, the next gpt-5.5 turn in an existing session can fail with:
APIError 401: input item ID does not belong to this connection
url: https://api.githubcopilot.com/responses
This is deterministically reproducible whenever the active Copilot connection changes underneath the session — either because the stored Copilot credential was rotated (e.g. switching between multiple Copilot accounts when one runs out of quota), or because the session was used with a different model/provider in between and is then switched back to github-copilot/gpt-5.5. It has a clear root cause (details below). It is distinct from #26886, which reports the same error string but as a transient/random upstream disconnect with no reproduction steps. This report is the deterministic case caused by a Copilot Responses-API connection change.
Root cause
Copilot gpt-5.5 uses the stateful OpenAI Responses API (/responses), not stateless Chat Completions. Each assistant turn's reasoning and text parts persist an openai.itemId handle in part metadata. On the next turn, OpenCode references these prior itemIds as input items (server-side state reuse) instead of re-sending full history.
These itemIds are bound to the specific Copilot Responses-API connection that created them. If the active connection differs from the one that produced the stored itemIds — because the stored Copilot credential was swapped, or because intervening turns went through a different provider/model and the session then switches back — OpenCode still references the old itemIds, the new connection does not recognize them, and the server rejects the request with 401 input item ID does not belong to this connection.
Evidence from session storage (a stored part, values redacted):
{
"type": "reasoning",
"metadata": {
"openai": {
"itemId": "PFf6cBEQ……(long opaque per-connection handle, redacted)",
"reasoningEncryptedContent": null
}
}
}
In affected sessions these itemId-bearing parts are not occasional: a single working session can accumulate well over a hundred parts (across reasoning, text, and tool types) each carrying an openai.itemId from the original connection. All of them become stale as soon as the active Copilot connection changes.
Why only Copilot gpt-5.5 is affected
- Copilot claude-opus-4.8 (and other Claude models): use the Anthropic Messages format (stateless), never reference an itemId, so a connection change has no effect — continues fine.
- OpenAI direct gpt-5.5: a separate provider/connection, does not reference Copilot's itemIds — continues fine.
- Copilot gpt-5.5: references the stale Copilot itemIds — fails.
Note on how the active Copilot connection gets changed
Two paths produce a connection change under an existing session:
- Credential rotation. There is currently no first-class
switch between multiple GitHub Copilot accounts (unlike the opencode.ai Console account, which has login / logout / switch). The Copilot auth plugin's authorize flow returns a single credential and writes it to the one fixed github-copilot key; re-running /connect overwrites the existing Copilot credential rather than adding a second account. So in practice the only way to rotate between Copilot accounts is to change the stored credential directly (editing auth.json, which on load is migrated into account.json and takes precedence while it exists).
- Switching to a different provider/model in the same session and then switching back to
github-copilot/gpt-5.5. Intervening turns served by another provider/model (for example OpenAI-direct gpt-5.5) do not produce Copilot-recognised itemIds, but the session still holds the original Copilot itemIds in earlier parts. When github-copilot/gpt-5.5 resumes, those original itemIds are sent over what is now a different Copilot Responses-API connection and are rejected.
Either way the trigger to hook on is "the active Copilot Responses-API connection differs from the one that produced the cached itemIds", not a UI-level account-switch event (which does not exist for Copilot).
Workarounds tried
/compact does not fix it. The compaction record stored in the session is essentially a tail_start_id marker: it shifts where the model's new context window starts, but it does not delete or rewrite the earlier parts that hold openai.itemId metadata. Those stale itemIds remain in the session store and are still referenced by the next Copilot Responses-API request, so the 401 reproduces immediately after compaction.
- Switching the session to
github-copilot/claude-opus-4.8 or to OpenAI-direct gpt-5.5 works (no itemId reference). Switching back to github-copilot/gpt-5.5 immediately re-triggers the 401, which is the same root cause as the credential-rotation case.
- The only consistently effective recovery today is starting a new session.
Suggested fix
When the active Copilot Responses-API connection changes (credential rotation, or resuming gpt-5.5 after intervening non-Copilot turns), invalidate / clear the cached Responses API itemId handles for affected sessions, including ones already persisted in parts. Alternatively (and more robustly), on receiving input item ID does not belong to this connection, automatically retry the request once without the stale itemId references, falling back to a full-history resend. The retry-on-error approach would make connection changes transparent for gpt-5.5 sessions and would also gracefully handle the transient/out-of-sync case in #26886.
Plugins
None
OpenCode version
First observed on 1.16.2; still reproducible on 1.17.3.
Steps to reproduce
Credential-rotation path:
- Authenticate the Copilot provider with token A.
- In a session, run several turns using
github-copilot/gpt-5.5.
- Replace the Copilot credential with token B (a different Copilot account, identical models/quota) — e.g. by editing
auth.json, since there is no multi-account switch for Copilot.
- In the same session, continue with
github-copilot/gpt-5.5.
- Observe
401 input item ID does not belong to this connection.
Model/provider-switch path (no credential change required):
- In a session, run several turns using
github-copilot/gpt-5.5 (accumulating itemId-bearing parts).
- In the same session, switch the model to a different provider/model (e.g. OpenAI-direct
gpt-5.5, or another Copilot model) and run at least one turn.
- Switch the session back to
github-copilot/gpt-5.5.
- Observe the same
401 input item ID does not belong to this connection.
- (Optional) Run
/compact between steps 2 and 3 and confirm it does not prevent the failure — earlier itemId-bearing parts remain in the session store.
In both paths, switching the session to github-copilot/claude-opus-4.8 continues without error (Claude does not reference Copilot itemIds).
Screenshot and/or share link
No response
Operating System
Windows 11
Terminal
Windows Terminal
Related
Description
When using the GitHub Copilot provider with gpt-5.5, the next gpt-5.5 turn in an existing session can fail with:
This is deterministically reproducible whenever the active Copilot connection changes underneath the session — either because the stored Copilot credential was rotated (e.g. switching between multiple Copilot accounts when one runs out of quota), or because the session was used with a different model/provider in between and is then switched back to
github-copilot/gpt-5.5. It has a clear root cause (details below). It is distinct from #26886, which reports the same error string but as a transient/random upstream disconnect with no reproduction steps. This report is the deterministic case caused by a Copilot Responses-API connection change.Root cause
Copilot gpt-5.5 uses the stateful OpenAI Responses API (
/responses), not stateless Chat Completions. Each assistant turn'sreasoningandtextparts persist anopenai.itemIdhandle in part metadata. On the next turn, OpenCode references these prior itemIds asinputitems (server-side state reuse) instead of re-sending full history.These itemIds are bound to the specific Copilot Responses-API connection that created them. If the active connection differs from the one that produced the stored itemIds — because the stored Copilot credential was swapped, or because intervening turns went through a different provider/model and the session then switches back — OpenCode still references the old itemIds, the new connection does not recognize them, and the server rejects the request with
401 input item ID does not belong to this connection.Evidence from session storage (a stored part, values redacted):
{ "type": "reasoning", "metadata": { "openai": { "itemId": "PFf6cBEQ……(long opaque per-connection handle, redacted)", "reasoningEncryptedContent": null } } }In affected sessions these itemId-bearing parts are not occasional: a single working session can accumulate well over a hundred parts (across
reasoning,text, andtooltypes) each carrying anopenai.itemIdfrom the original connection. All of them become stale as soon as the active Copilot connection changes.Why only Copilot gpt-5.5 is affected
Note on how the active Copilot connection gets changed
Two paths produce a connection change under an existing session:
switchbetween multiple GitHub Copilot accounts (unlike the opencode.ai Console account, which haslogin/logout/switch). The Copilot auth plugin'sauthorizeflow returns a single credential and writes it to the one fixedgithub-copilotkey; re-running/connectoverwrites the existing Copilot credential rather than adding a second account. So in practice the only way to rotate between Copilot accounts is to change the stored credential directly (editingauth.json, which on load is migrated intoaccount.jsonand takes precedence while it exists).github-copilot/gpt-5.5. Intervening turns served by another provider/model (for example OpenAI-directgpt-5.5) do not produce Copilot-recognised itemIds, but the session still holds the original Copilot itemIds in earlier parts. Whengithub-copilot/gpt-5.5resumes, those original itemIds are sent over what is now a different Copilot Responses-API connection and are rejected.Either way the trigger to hook on is "the active Copilot Responses-API connection differs from the one that produced the cached itemIds", not a UI-level account-switch event (which does not exist for Copilot).
Workarounds tried
/compactdoes not fix it. The compaction record stored in the session is essentially atail_start_idmarker: it shifts where the model's new context window starts, but it does not delete or rewrite the earlierpartsthat holdopenai.itemIdmetadata. Those stale itemIds remain in the session store and are still referenced by the next Copilot Responses-API request, so the 401 reproduces immediately after compaction.github-copilot/claude-opus-4.8or to OpenAI-directgpt-5.5works (no itemId reference). Switching back togithub-copilot/gpt-5.5immediately re-triggers the 401, which is the same root cause as the credential-rotation case.Suggested fix
When the active Copilot Responses-API connection changes (credential rotation, or resuming gpt-5.5 after intervening non-Copilot turns), invalidate / clear the cached Responses API
itemIdhandles for affected sessions, including ones already persisted inparts. Alternatively (and more robustly), on receivinginput item ID does not belong to this connection, automatically retry the request once without the stale itemId references, falling back to a full-history resend. The retry-on-error approach would make connection changes transparent for gpt-5.5 sessions and would also gracefully handle the transient/out-of-sync case in #26886.Plugins
None
OpenCode version
First observed on 1.16.2; still reproducible on 1.17.3.
Steps to reproduce
Credential-rotation path:
github-copilot/gpt-5.5.auth.json, since there is no multi-account switch for Copilot.github-copilot/gpt-5.5.401 input item ID does not belong to this connection.Model/provider-switch path (no credential change required):
github-copilot/gpt-5.5(accumulating itemId-bearing parts).gpt-5.5, or another Copilot model) and run at least one turn.github-copilot/gpt-5.5.401 input item ID does not belong to this connection./compactbetween steps 2 and 3 and confirm it does not prevent the failure — earlier itemId-bearingpartsremain in the session store.In both paths, switching the session to
github-copilot/claude-opus-4.8continues without error (Claude does not reference Copilot itemIds).Screenshot and/or share link
No response
Operating System
Windows 11
Terminal
Windows Terminal
Related