L'API ha verificato la firma di un blocco thinking che hai reinviato, ma la verifica non è riuscita: la firma è stata troncata, alterata o reinviata vuota, oppure il blocco non è mai stato firmato da Claude — o, con Claude Fable 5.1 e Claude Opus 5.5, qualcosa di precedente nella conversazione è cambiato. Reinviare la stessa cronologia fallisce ogni volta nello stesso modo. Trova cosa l'ha danneggiata, quindi rimuovi una volta sola i blocchi thinking da quella conversazione e continua — perdi il ragionamento precedente del modello, non la conversazione.
L’errore
// Through Kunavo: the upstream message as it reaches you, typed as Anthropic
// types a 400; no request_id field, the upstream's own id is appended instead:
{"type":"error","error":{"type":"invalid_request_error","message":"messages.1.content.0: Invalid `signature` in `thinking` block (request id: …)"}}
// (the message path, any masking of it and the appended request id vary by upstream)
// From Anthropic's API directly:
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "messages.1.content.0: Invalid `signature` in `thinking` block"
},
"request_id": "req_011C..."
}
// messages.{i}.content.{j}: i = position in messages[], j = block index. Both vary.
// An upstream can mask that path (***.***) and append its own request id, as above.
// Claude Code prints the body after "API Error: 400".
// On Claude Fable 5.1 and Claude Opus 5.5 the message can continue:
// "... The block is bound to a different conversation. Remove the block, or set
// `thinking.block_binding.prefix_mismatch_behavior` to "drop_block"."Cause e soluzioni in breve
| Causa | Soluzione |
|---|---|
| La firma è stata troncata, svuotata o modificata prima di essere reinviata | Archivia e riproduci ogni blocco esattamente come è stato restituito. Lascia che l'SDK assembli i turni trasmessi in streaming, così signature_delta non va perso. |
| Il blocco non è mai stato firmato da Claude | Un modello non-Claude dietro un URL compatibile con Anthropic, oppure un proxy che genera le proprie firme. Reinvia quei turni solo come testo e tool_use. |
| Hai cambiato URL di base, account o accesso durante la conversazione | Claude Code 2.1.152+ rimuove le firme obsolete dopo il cambio di modello o di accesso. Nel tuo codice, rimuovi una volta i blocchi thinking se la prima richiesta dopo un cambio fallisce. |
| “Il blocco è associato a una conversazione diversa” (Fable 5.1, Opus 5.5) | Il prompt di sistema, gli strumenti o un messaggio precedente sono cambiati. Mantieni la cronologia in modalità append-only, oppure attiva drop_block (richiede un'intestazione beta). |
| Un proxy o un gateway riscrive la cronologia durante il passaggio | Le sue riscritture vengono considerate tue modifiche. Riproduci la richiesta direttamente sull'API per stabilire se è la causa. |
Leggi quale verifica è fallita
La formulazione lo indica. Un messaggio che si ferma a “Invalid `signature` in `thinking` block” significa che la firma stessa non è stata verificata: Anthropic elenca come cause una firma troncata, alterata o reinviata vuota (https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting, aggiornato a settembre 2026), e la pagina sul thinking preservato parla di una firma manomessa o non decifrabile che restituisce sempre un errore 400. Un percorso mascherato come ***.***.content.0 o un ID richiesta aggiunto da un gateway non cambia questo; ciò che conta è se segue una frase sulla conversazione. Su Claude Fable 5.1 e Claude Opus 5.5 le stesse parole possono continuare con “The block is bound to a different conversation” — si tratta di una verifica diversa, descritta nell'ultimo passaggio. Un terzo messaggio, “blocks in the latest assistant message cannot be modified”, significa che il turno assistant più recente è stato modificato, filtrato, riordinato o ricostruito; il testo thinking modificato produce questo errore, non un errore di firma. Ritentare con lo stesso corpo non risolve nessuno dei due problemi.
Invalid `signature` in `thinking` block
-> the signature did not verify: truncated, altered, empty, or not Claude's
Invalid `signature` in `thinking` block. The block is bound to a different conversation. ...
-> Fable 5.1 / Opus 5.5: system, tools or an earlier message changed after the block was made
`thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified
-> the newest assistant turn was edited, filtered, reordered or rebuilt before it was sent backReinvia i turni assistant esattamente come sono stati restituiti
Ogni blocco thinking contiene una firma — una copia crittografata dell'intero ragionamento — e l'API la usa per verificare che il blocco sia stato generato da Claude (https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-encryption). Aggiungi l'elenco content della risposta senza modificarlo: blocchi thinking, redacted_thinking e tool_use, inclusi i blocchi thinking il cui testo è vuoto, impostazione di visualizzazione predefinita nei modelli più recenti. Durante lo streaming, la firma arriva in un unico signature_delta subito prima della chiusura del blocco; un accumulatore scritto manualmente che lo perde archivia una firma vuota, e un blocco reinviato con una firma vuota fallisce. Il consiglio di Anthropic è lasciare che sia l'SDK ad assemblare il messaggio. L'ordine delle chiavi JSON e gli spazi bianchi non contano — contano i valori.
import anthropic
client = anthropic.Anthropic(base_url="https://api.kunavo.com", api_key="sk-kn-...")
tools = [{
"name": "get_weather",
"description": "Current weather for a city.",
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
}]
messages = [{"role": "user", "content": "What's the weather in Paris?"}]
with client.messages.stream(
model="claude-sonnet-4-6",
max_tokens=16000,
thinking={"type": "adaptive"},
tools=tools,
messages=messages,
) as stream:
final = stream.get_final_message() # signature_delta already applied
# Append the content list untouched: thinking, redacted_thinking, tool_use.
messages.append({"role": "assistant", "content": final.content})
# Not this: a store that keeps the text but not the signature replays
# {"type": "thinking", "thinking": "...", "signature": ""} -> this 400.Mantieni il thinking degli altri backend fuori dalla cronologia di Claude
Secondo la documentazione di Anthropic, il passaggio da un modello Claude a un altro sulla sua API non dovrebbe causare questo errore: invita a continuare a inviare i blocchi durante il cambio, elimina senza errore quelli che il nuovo modello non può leggere e documenta le firme come portabili tra Claude API, Amazon Bedrock e Google Cloud (https://platform.claude.com/docs/en/build-with-claude/thinking, aggiornato a settembre 2026). Ciò che non può verificare è un blocco mai firmato da Claude. Le segnalazioni pubbliche riguardano cronologie passate da un altro backend: una sessione Claude Code eseguita su un backend GLM e poi tornata ad Anthropic (github.com/anthropics/claude-code/issues/21726), turni Gemini trasformati da un proxy in blocchi thinking di Claude con firme proprie (github.com/router-for-me/CLIProxyAPI/issues/1584), una sessione Claude Code passata a un'altra chiave a metà e poi tornata indietro (github.com/lbjlaq/Antigravity-Manager/issues/388). Per i turni prodotti da un modello non-Claude, il consiglio di Anthropic è reinviare l'output di quel modello solo come contenuto text e tool_use.
def as_foreign_turn(content: list[dict]) -> list[dict]:
"""A turn a non-Claude model produced: keep what it said and did,
never its thinking blocks, which Claude cannot verify."""
return [b for b in content if b["type"] in ("text", "tool_use")]Recupera una conversazione che già fallisce
Rimuovi una volta dalla cronologia archiviata i blocchi thinking e redacted_thinking — rimuoverli tutti è la soluzione più semplice; per la variante “associato a una conversazione diversa”, il minimo indicato da Anthropic è il blocco nominato e tutti quelli successivi — mantieni ogni altro blocco nella sua posizione, salva la cronologia e continua. Anthropic indica questa procedura come recupero per una sessione salvata che non può più essere riprodotta (https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#faq); quando una firma non viene verificata, l'unica altra via d'uscita è riprodurre il blocco esattamente come è stato restituito, se lo possiedi ancora. Claude Code rimuove autonomamente il thinking precedente quando l'API rifiuta una firma. Dopo aver rimosso i blocchi e proseguito, non reinserirli: su Fable 5.1, un blocco rimosso e poi reinserito invalida il thinking prodotto mentre era assente. Il modello risponde senza il ragionamento precedente, e da quel punto il nuovo thinking è valido. In Claude Code, la versione 2.1.152 (27 maggio 2026, https://code.claude.com/docs/en/changelog) rimuove le firme obsolete dopo un cambio di modello o di accesso, e la guida del suo gateway indica che ritenta un rifiuto della firma senza i blocchi thinking precedenti — ma il tentativo riconosce il testo dell'errore upstream, e un gateway che avvolge gli errori in un proprio envelope può impedirlo (https://code.claude.com/docs/en/llm-gateway-protocol#automatic-retry-and-error-forwarding).
THINKING = {"thinking", "redacted_thinking"}
def block_type(b) -> str:
return b["type"] if isinstance(b, dict) else b.type # dicts or SDK objects
def strip_thinking(messages: list[dict]) -> list[dict]:
"""One-time recovery: drop every thinking block, keep everything else."""
out = []
for m in messages:
content = m["content"]
if m["role"] == "assistant" and isinstance(content, list):
kept = [b for b in content if block_type(b) not in THINKING]
content = kept or [{"type": "text", "text": "(no visible reply)"}] # keep the turn non-empty
out.append({**m, "content": content})
return out
messages = strip_thinking(messages) # save this version; never re-add the blocksSu Fable 5.1, mantieni fisso il prefisso — oppure attiva drop_block
“Associato a una conversazione diversa” è la verifica del thinking preservato: su Claude Fable 5.1 e Claude Opus 5.5, un blocco riprodotto è valido solo finché il prompt di sistema, gli strumenti e ogni messaggio precedente rimangono invariati. Anthropic lo applica per impostazione predefinita agli account creati il 31 agosto 2026 o successivamente (https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#enforcement); dietro un gateway quell'account non è tuo, quindi presumi che sia attivo. Mantieni fissi sistema e strumenti per la sessione e aggiungi contenuti invece di modificare. Per fare in modo che le richieste continuino ad avere successo mentre individui la modifica, invia l'intestazione beta thinking-binding-controls-2026-08-01 con prefix_mismatch_behavior impostato su drop_block; senza questa intestazione il campo stesso viene rifiutato con “block_binding: Extra inputs are not permitted” (https://platform.claude.com/docs/en/api/errors).
# Anthropic's API directly. The field needs the beta header; Kunavo forwards it (see below).
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: thinking-binding-controls-2026-08-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-fable-5-1",
"max_tokens": 16000,
"thinking": {
"type": "adaptive",
"block_binding": {"prefix_mismatch_behavior": "drop_block"}
},
"messages": [{"role": "user", "content": "..."}]
}'Se chiami tramite Kunavo
Kunavo inoltra i blocchi thinking e redacted_thinking tramite /v1/messages così come sono stati inviati, inclusi firma e dati — le uniche modifiche alla richiesta sono l'ID del modello e, sui modelli che li rifiutano, la rimozione di temperature, top_p e top_k — e restituisce il corpo della risposta, in streaming o meno, così come è stato inviato dall'upstream. A settembre 2026 ogni modello Claude viene servito tramite un unico canale upstream senza fallback, quindi il routing di Kunavo non sposta una conversazione tra provider e un 400 non viene mai ritentato altrove. Non abbiamo testato lo spostamento di una conversazione tra Anthropic diretto e Kunavo, quindi prevedi che la prima richiesta dopo tale cambio debba avere il thinking rimosso. Dal 24 settembre 2026 Kunavo inoltra la beta thinking-binding-controls-2026-08-01; in un test svolto quel giorno, il canale che serviva Claude ha accettato block_binding su Claude Fable 5.1 con o senza l'intestazione e non abbiamo osservato la rimozione di alcun blocco. Il rifiuto arriva come HTTP 400 di tipo invalid_request_error, senza un campo request_id, e contiene il testo del messaggio upstream — che può mascherare il percorso messages.N e terminare con l'ID richiesta dell'upstream — quindi cerca lo stato e le parole “Invalid `signature` in `thinking` block”. La rimozione e il nuovo tentativo automatici di Claude Code si basano su quella formulazione: Claude Code 2.1.280, indirizzato a un server di test che rispondeva con questo envelope, ha rimosso i blocchi thinking e ritentato. Non abbiamo attivato l'errore tramite Kunavo, quindi se una sessione continua a fallire a ogni turno, iniziane una nuova. Le richieste fallite non vengono addebitate. Ciò che l'endpoint nativo inoltra senza modifiche è elencato in riferimento all'API Messages.
Domande frequenti
Che cosa significa “Invalid `signature` in `thinking` block”?
L'API non ha potuto verificare un blocco thinking che hai reinviato. Ogni blocco thinking contiene una firma — una copia crittografata del ragionamento di Claude — e la verifica fallisce quando la firma è stata troncata, alterata o reinviata vuota, oppure quando il blocco non è mai stato firmato da Claude. È un errore 400, non transitorio: la stessa richiesta fallisce ogni volta.
Le firme dei blocchi thinking scadono?
La documentazione di Anthropic non menziona una scadenza. Nel tracker anthropic-sdk-python (issue #1598, agosto 2026), una risposta di un account che GitHub identifica come collaboratore afferma che non scadono e che la verifica fallisce quando il blocco che raggiunge l'API è diverso da quello restituito — si tratta del commento a un issue, non della documentazione. Se una sessione salvata che prima funzionava ora fallisce, verifica cosa potrebbe aver modificato i blocchi archiviati o il percorso che hanno seguito: il tuo livello di archiviazione, un proxy o un cambio di backend.
Posso semplicemente eliminare i blocchi thinking e continuare?
Sì. Anthropic lo indica come recupero per una sessione salvata che non può essere riprodotta, e Claude Code rimuove autonomamente il thinking precedente quando una firma viene rifiutata. Rimuovi i blocchi thinking e redacted_thinking — rimuoverli tutti è la soluzione più semplice — mantieni gli altri blocchi e ritenta una volta. Il modello perde il ragionamento precedente, non la conversazione; al di fuori dell'uso degli strumenti, la documentazione di Anthropic consente comunque di omettere il thinking dei turni precedenti.
Perché succede dopo il cambio di modello o provider?
La documentazione di Anthropic afferma che il passaggio tra modelli Claude sulla sua API rimuove senza errori i blocchi che il nuovo modello non può leggere e che le firme funzionano tra Claude API, Amazon Bedrock e Google Cloud. Claude Code ha comunque dovuto correggere sessioni bloccate da firme obsolete dopo un cambio di modello o di accesso (2.1.152), e le segnalazioni pubbliche riguardano cronologie passate da qualcosa che Claude non può verificare — un modello non-Claude dietro lo stesso URL di base, un proxy che genera le proprie firme o un client che le ha perse. Rimuovi una volta i blocchi thinking dopo il cambio.
Claude Code risolve automaticamente il problema?
Le versioni recenti ci provano. Dalla versione 2.1.152 rimuove le firme obsolete dopo un cambio di modello o di accesso e ritenta un rifiuto della firma senza i blocchi thinking precedenti. Il tentativo riconosce il testo dell'errore upstream, e la guida del gateway di Anthropic afferma che un gateway che avvolge gli errori in un proprio envelope può impedirlo. Esegui prima claude update; se una sessione continua a fallire a ogni turno, iniziane una nuova.
Guide correlate
- API Claude 400 «tool_use ids were found without tool_result blocks» — la regola dell'ordine
- Claude Code Router — indirizza Claude Code a qualsiasi modello oppure salta del tutto il router
- Errori di streaming LLM — interruzioni SSE, stream bloccati e utilizzo mancante
- Claude Code “context_management: Extra inputs are not permitted” — l'header beta che non è arrivato
Ulteriori dettagli sul significato degli errori sono disponibili in riferimento agli errori; ottenere una chiave richiede un minuto tramite registrazione e la guida all’autenticazione.