You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Error 400 when using muse spark 1.3 contributor on some longer threads #141
Thanks for the report — the input[3].call_id detail is genuinely useful, and it lines up with a failure class we've been seeing on the Responses wire.
What we observe on our side: the same shape of failure on openai-responses threads through the CommandCode provider, but the gateway payload we get back is generic — {"type":"invalid_request_error","message":"invalid request error trace_id: <id>"} with no field detail (plus one 524 upstream). Every occurrence so far has been on a thread that switched models mid-conversation, which matches your "doesn't happen on fresh threads". So your message gives us the missing half: it's the call_id bound (<= 64) that trips.
Our working hypothesis, host-side: Responses tool-call IDs are stored compounded as <call_id>|<item_id> and must be split — never forwarded joined — when the history is replayed into /responses. pi core does sanitize and bound both halves (truncate to 64, foreign item IDs hashed into fc_<hash>), but it only normalizes when the source message came from a different model/provider — i.e. exactly your mid-thread switch. A host that keeps the compound (or re-prefixes it) on the very first replay after a switch would produce a call_id over the limit and a 400 on input[N].call_id.
To point the fix at the right layer, four things would settle it:
Host + version: pi --version, or OMP (omp --version)? The package supports both, and each ships its own converter.
Extension version: the pi-commandcode-provider version you're on.
trace_id from one of the 400s (yours may carry one too) — that lets us pull the gateway-side request that was rejected.
The switch itself: did you change models inside a live session (and roughly how long was the thread at that point), or did you reopen/fork it? Which model did you switch from?
If it's cheap to reproduce, a single failing call with the error body pasted in full is enough — no need to scrub anything else.
Workaround in the meantime: a fresh session, or staying on one model for the thread, avoids the replay path that triggers it.
Adding bug + provider and assigning myself for tracking.
switching from muse spark contributor 1.3 free on pi-opencode-direct, happens on a variety of threads but can't reproduce manually with testing, my current thread is 70% of 1M context
Thanks — knowing this is pi 1.0.4 and that the source model is Muse Spark through pi-opencode-direct helps.
I should qualify my earlier hypothesis: we have not established that your field-specific error and the generic 400s observed on our side have the same cause. A stored compound ID longer than 64 characters is not itself invalid; the length of the call_id component sent on the wire is what matters. The absence of a trace_id does not establish which gateway generated the error either.
I ran an offline check against pi 1.0.4's Responses converter using a synthetic 80-character ID:
Replayed history
Emitted call_id length
Foreign-model tool call + matching result
64
Same-model tool call + matching result
80
Tool result without its corresponding assistant tool call
80
So there are paths where an overlong ID can reach the request, but this is a converter-level check, not a reproduction of your session. We still need to connect the failing history to one of those paths before attributing the cause.
Could you confirm:
The exact provider/model selected on the turn that fails — is the destination commandcode/meta/muse-spark-1.3-contributor? Also, is the extension version specifically 0.7.6?
Whether the affected session had been compacted or its history edited before the error. If convenient, metadata only around the relevant tool call/result would help: the source message's provider, api, model, and the lengths of each ID component before/after |.
No need to share the full thread, prompts, tool arguments/results, or credentials. Starting a fresh session remains the practical workaround reported so far; I'll keep this open while we narrow down the replay path.
I have managed to reproduce it on a fresh/dummy thread, this should be the answer to your questions, here you go: 2026-10-08T01-49-33-514Z_01a11933-95ca-71a9-aba7-4e203a48d199.json (it's a jsonl file, however github doesn't support uploading files with the jsonl extension)
the extension version is 0.7.6
Thanks for the dummy-session repro and the version confirmation — it helped narrow this down.
Replaying its history through the native Responses path produced IDs within the 64-character limit. A local test of the extension's fallback path (/alpha/generate), however, shows that it forwards the compound tool-call IDs unchanged: 73 characters in this case. That gives us a concrete lead, but we still need to confirm which path your failing request uses.
Could you run /commandcode-status immediately after the next 400, in the same running pi instance, and paste just the line:
transport: provider
or:
transport: generate
Please do this before restarting pi. No credentials or additional session content are needed. That one line will tell us which request path to investigate next.
That one line settles it — thanks. transport: generate confirms the failing request goes through the extension's /alpha/generate fallback, not the Provider API Responses path.
Replaying your dummy session's history through that fallback's serializer shows the cause: the 73-character compound Responses tool-call ids (call_<32hex>|fc_<32hex>) are forwarded unchanged, and the generate backend rejects call_id values longer than 64 characters. That matches your input[3].call_id 400 exactly.
A fix is in progress on our side: the fallback shortens overlong tool-call ids to the 64-character limit with a deterministic per-request mapping shared by calls and their results, so pairing is preserved and distinct ids never collide. Short ids pass through unchanged, and the Provider API path is untouched. It will ship in an upcoming release — no action needed on your end.
I'll update this thread once it's out. Thanks again for the repro and the status line — both were decisive.
Activity
pierreraby commentedon Oct 7, 2026
Thanks for the report — the
input[3].call_iddetail is genuinely useful, and it lines up with a failure class we've been seeing on the Responses wire.What we observe on our side: the same shape of failure on
openai-responsesthreads through the CommandCode provider, but the gateway payload we get back is generic —{"type":"invalid_request_error","message":"invalid request error trace_id: <id>"}with no field detail (plus one524upstream). Every occurrence so far has been on a thread that switched models mid-conversation, which matches your "doesn't happen on fresh threads". So your message gives us the missing half: it's thecall_idbound (<= 64) that trips.Our working hypothesis, host-side: Responses tool-call IDs are stored compounded as
<call_id>|<item_id>and must be split — never forwarded joined — when the history is replayed into/responses. pi core does sanitize and bound both halves (truncate to 64, foreign item IDs hashed intofc_<hash>), but it only normalizes when the source message came from a different model/provider — i.e. exactly your mid-thread switch. A host that keeps the compound (or re-prefixes it) on the very first replay after a switch would produce acall_idover the limit and a 400 oninput[N].call_id.To point the fix at the right layer, four things would settle it:
pi --version, or OMP (omp --version)? The package supports both, and each ships its own converter.pi-commandcode-providerversion you're on.trace_idfrom one of the 400s (yours may carry one too) — that lets us pull the gateway-side request that was rejected.If it's cheap to reproduce, a single failing call with the error body pasted in full is enough — no need to scrub anything else.
Workaround in the meantime: a fresh session, or staying on one model for the thread, avoids the replay path that triggers it.
Adding
bug+providerand assigning myself for tracking.szpoont commentedon Oct 7, 2026
pierreraby commentedon Oct 7, 2026
Thanks — knowing this is pi 1.0.4 and that the source model is Muse Spark through pi-opencode-direct helps.
I should qualify my earlier hypothesis: we have not established that your field-specific error and the generic 400s observed on our side have the same cause. A stored compound ID longer than 64 characters is not itself invalid; the length of the
call_idcomponent sent on the wire is what matters. The absence of atrace_iddoes not establish which gateway generated the error either.I ran an offline check against pi 1.0.4's Responses converter using a synthetic 80-character ID:
call_idlengthSo there are paths where an overlong ID can reach the request, but this is a converter-level check, not a reproduction of your session. We still need to connect the failing history to one of those paths before attributing the cause.
Could you confirm:
commandcode/meta/muse-spark-1.3-contributor? Also, is the extension version specifically 0.7.6?provider,api,model, and the lengths of each ID component before/after|.No need to share the full thread, prompts, tool arguments/results, or credentials. Starting a fresh session remains the practical workaround reported so far; I'll keep this open while we narrow down the replay path.
szpoont commentedon Oct 8, 2026
I have managed to reproduce it on a fresh/dummy thread, this should be the answer to your questions, here you go:
2026-10-08T01-49-33-514Z_01a11933-95ca-71a9-aba7-4e203a48d199.json (it's a jsonl file, however github doesn't support uploading files with the jsonl extension)
the extension version is 0.7.6
pierreraby commentedon Oct 8, 2026
Thanks for the dummy-session repro and the version confirmation — it helped narrow this down.
Replaying its history through the native Responses path produced IDs within the 64-character limit. A local test of the extension's fallback path (
/alpha/generate), however, shows that it forwards the compound tool-call IDs unchanged: 73 characters in this case. That gives us a concrete lead, but we still need to confirm which path your failing request uses.Could you run
/commandcode-statusimmediately after the next 400, in the same running pi instance, and paste just the line:or:
Please do this before restarting pi. No credentials or additional session content are needed. That one line will tell us which request path to investigate next.
szpoont commentedon Oct 8, 2026
transport: generatepierreraby commentedon Oct 8, 2026
That one line settles it — thanks.
transport: generateconfirms the failing request goes through the extension's/alpha/generatefallback, not the Provider API Responses path.Replaying your dummy session's history through that fallback's serializer shows the cause: the 73-character compound Responses tool-call ids (
call_<32hex>|fc_<32hex>) are forwarded unchanged, and the generate backend rejectscall_idvalues longer than 64 characters. That matches yourinput[3].call_id400 exactly.A fix is in progress on our side: the fallback shortens overlong tool-call ids to the 64-character limit with a deterministic per-request mapping shared by calls and their results, so pairing is preserved and distinct ids never collide. Short ids pass through unchanged, and the Provider API path is untouched. It will ship in an upcoming release — no action needed on your end.
I'll update this thread once it's out. Thanks again for the repro and the status line — both were decisive.