API가 반환된 thinking 블록의 서명을 확인했지만 검증에 실패했습니다. 서명이 잘리거나 변경되었거나 비어 있는 상태로 반환되었거나, 해당 블록이 Claude에 의해 서명된 적이 없었기 때문입니다. 또는 Claude Fable 5.1 및 Claude Opus 5.5에서는 대화 앞부분의 내용이 변경되었을 수도 있습니다. 같은 기록을 다시 보내도 매번 같은 방식으로 실패합니다. 무엇이 손상시켰는지 찾은 다음, 해당 대화에서 thinking 블록을 한 번 제거하고 계속 진행하세요 — 모델의 이전 추론은 잃지만 대화는 잃지 않습니다.
오류
// 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"."원인과 해결 방법 한눈에 보기
| 원인 | 해결 방법 |
|---|---|
| 반환되기 전에 서명이 잘리거나 비워졌거나 편집되었습니다 | 각 블록을 반환된 그대로 저장하고 재생하세요. SDK가 스트리밍된 턴을 조립하도록 하여 signature_delta가 유실되지 않게 하세요. |
| 블록이 Claude에 의해 서명된 적이 없습니다 | Anthropic 호환 URL 뒤의 비-Claude 모델 또는 자체 서명을 작성하는 프록시일 수 있습니다. 해당 턴은 text와 tool_use만 포함해 반환하세요. |
| 대화 중간에 base URL, 계정 또는 로그인을 전환했습니다 | Claude Code 2.1.152+는 모델 또는 로그인 전환 후 오래된 서명을 제거합니다. 직접 작성한 코드에서는 전환 후 첫 요청이 실패할 경우 thinking을 한 번 제거하세요. |
| “블록이 다른 대화에 연결되어 있습니다” (Fable 5.1, Opus 5.5) | 시스템 프롬프트, 도구 또는 이전 메시지가 변경되었습니다. 기록을 추가 전용으로 유지하거나 drop_block을 선택하세요(beta 헤더 필요). |
| 프록시 또는 게이트웨이가 전달 과정에서 기록을 다시 작성합니다 | 이러한 재작성은 사용자가 편집한 것으로 간주됩니다. 이를 확인하거나 배제하려면 API에 직접 요청해 보세요. |
실패한 검사를 확인하세요
문구가 알려 줍니다. 메시지가 “`thinking` 블록의 잘못된 `signature`”에서 끝난다면 서명 자체가 검증되지 않은 것입니다. Anthropic은 잘림, 변경 또는 빈 상태로 반환됨을 원인으로 나열하며(2026년 9월 기준, https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting), 보존된 thinking 페이지에서는 이를 변조되었거나 복호화할 수 없는 서명이라고 설명하고 항상 400을 반환한다고 합니다. ***.***.content.0처럼 경로가 마스킹되었거나 게이트웨이가 요청 ID를 덧붙였더라도 달라지지 않습니다. 중요한 것은 뒤에 대화에 관한 문장이 이어지는지입니다. Claude Fable 5.1 및 Claude Opus 5.5에서는 같은 문구 뒤에 “블록이 다른 대화에 연결되어 있습니다”가 이어질 수 있습니다 — 이는 마지막 단계에서 다루는 다른 검사입니다. 세 번째 메시지인 “최신 assistant 메시지의 블록은 수정할 수 없습니다”는 가장 최근 assistant 턴이 편집, 필터링, 순서 변경 또는 재구성되었다는 뜻입니다. 편집된 thinking 텍스트가 있으면 서명 오류가 아니라 이 오류가 발생합니다. 같은 본문을 재시도해도 어느 오류도 해결되지 않습니다.
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 backassistant 턴을 반환된 그대로 다시 보내세요
각 thinking 블록에는 서명이 포함되어 있습니다 — 전체 추론의 암호화된 사본이며, API는 이를 사용해 해당 블록이 Claude에 의해 생성되었는지 확인합니다(https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-encryption). 응답의 content 목록을 수정하지 않고 그대로 추가하세요: thinking, redacted_thinking 및 tool_use 블록을 포함하며, 텍스트가 비어 있는 thinking 블록도 포함합니다. 이는 최신 모델의 기본 표시 방식입니다. 스트리밍 중에는 블록이 닫히기 직전에 서명이 하나의 signature_delta로 도착합니다. 따라서 직접 만든 누적기가 이를 놓치면 빈 서명이 저장되고, 빈 서명과 함께 보낸 블록은 실패합니다. Anthropic은 SDK가 메시지를 조립하도록 권장합니다. JSON 키 순서와 공백은 중요하지 않습니다 — 값이 중요합니다.
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.다른 백엔드의 thinking을 Claude 기록에서 제외하세요
Anthropic 문서에 따르면 자체 API에서 Claude 모델 간에 전환해도 원칙적으로 이 오류가 발생하지 않습니다. 전환할 때도 블록을 계속 보내라고 안내하며, 새 모델이 읽을 수 없는 블록은 오류 없이 삭제하고, 서명이 Claude API, Amazon Bedrock 및 Google Cloud 간에 호환된다고 설명합니다(https://platform.claude.com/docs/en/build-with-claude/thinking, 2026년 9월 기준). Claude가 서명하지 않은 블록은 검증할 수 없습니다. 공개된 사례에는 다른 백엔드를 거친 기록이 포함됩니다. GLM 백엔드에서 실행한 뒤 Anthropic으로 돌아온 Claude Code 세션(github.com/anthropics/claude-code/issues/21726), 자체 서명을 사용해 Gemini 턴을 Claude thinking 블록처럼 꾸민 프록시(github.com/router-for-me/CLIProxyAPI/issues/1584), 세션 중간에 다른 키로 전환했다가 돌아온 Claude Code 세션(github.com/lbjlaq/Antigravity-Manager/issues/388) 등이 있습니다. 비-Claude 모델이 생성한 턴은 Anthropic의 권고대로 해당 모델의 출력을 text와 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")]이미 실패하는 대화를 복구하세요
저장된 기록에서 thinking 및 redacted_thinking 블록을 한 번 제거하세요 — 모두 제거하는 것이 가장 간단합니다. “다른 대화에 연결됨” 변형의 경우 Anthropic이 명시한 최소 범위는 이름이 지정된 블록과 그 뒤의 모든 블록입니다. 다른 모든 블록은 원래 위치에 유지하고, 기록을 저장한 뒤 계속 진행하세요. Anthropic은 더 이상 재생할 수 없는 저장 세션의 복구 방법으로 이를 제시합니다(https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#faq). 서명이 검증되지 않을 때 가능한 다른 방법은 반환된 그대로 블록을 다시 재생하는 것뿐이며, 해당 블록을 아직 가지고 있어야 합니다. Claude Code는 API가 서명을 거부하면 이전 thinking을 직접 제거합니다. 블록을 제거하고 진행한 뒤에는 다시 넣지 마세요. Fable 5.1에서는 제거된 블록을 다시 넣으면 해당 블록이 없던 동안 생성된 thinking이 무효화됩니다. 모델은 이전 추론 없이 답변하며, 그 시점부터 새 thinking은 유효합니다. Claude Code 2.1.152(2026년 5월 27일, https://code.claude.com/docs/en/changelog)는 모델 또는 로그인 전환 후 오래된 서명을 제거하고, 게이트웨이 가이드는 이전 thinking 블록 없이 서명 거부를 재시도한다고 설명합니다. 그러나 이 재시도는 upstream 오류 문구를 기준으로 하므로, 오류를 자체 봉투로 감싸는 게이트웨이는 이를 깨뜨릴 수 있습니다(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 blocksFable 5.1에서는 접두부를 고정하거나 drop_block을 선택하세요
“다른 대화에 연결됨”은 보존된 thinking 검사입니다. Claude Fable 5.1 및 Claude Opus 5.5에서는 시스템 프롬프트, 도구, 모든 이전 메시지가 변경되지 않은 경우에만 재생된 블록이 유효합니다. Anthropic은 2026년 8월 31일 이후 생성된 계정에 이를 기본적으로 적용합니다(https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#enforcement). 게이트웨이 뒤에서는 해당 계정이 사용자의 계정이 아니므로 적용된다고 가정하세요. 세션 동안 시스템과 도구를 고정하고, 편집하지 말고 추가하세요. 편집을 찾는 동안에도 요청이 성공하도록 하려면 thinking-binding-controls-2026-08-01 beta 헤더를 보내고 prefix_mismatch_behavior을 drop_block으로 설정하세요. 이 헤더가 없으면 해당 필드 자체가 “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": "..."}]
}'Kunavo를 통해 호출하는 경우
Kunavo는 thinking 및 redacted_thinking 블록을 서명과 데이터까지 포함해 전송된 그대로 /v1/messages를 통해 전달합니다. 유일한 요청 변경은 모델 ID와, 이를 거부하는 모델에서 temperature, top_p 및 top_k를 제거하는 것입니다. 그리고 스트리밍 여부와 관계없이 upstream이 보낸 응답 본문을 그대로 반환합니다. 2026년 9월 기준 각 Claude 모델은 하나의 upstream 채널을 통해 제공되며 fallback이 없습니다. 따라서 Kunavo의 라우팅은 대화를 다른 제공업체로 이동하지 않고, 400 오류도 다른 곳으로 재시도하지 않습니다. Anthropic 직접 연결과 Kunavo 사이에서 대화를 이동하는 것은 테스트하지 않았으므로, 이러한 전환 후 첫 요청에서는 thinking을 제거해야 할 것으로 예상하세요. 2026년 9월 24일부터 Kunavo는 thinking-binding-controls-2026-08-01 beta를 전달합니다. 같은 날 진행한 테스트에서 Claude를 제공하는 채널은 헤더 유무와 관계없이 Claude Fable 5.1의 block_binding을 허용했으며, 블록을 삭제하는 경우는 확인하지 못했습니다. 거부 응답은 HTTP 400으로 도착하며 오류 유형은 invalid_request_error이고 request_id 필드는 없습니다. upstream의 메시지 텍스트를 포함하며, 이 텍스트는 messages.N 경로를 마스킹하고 upstream 자체 요청 ID로 끝날 수 있습니다. 따라서 상태 코드와 “Invalid `signature` in `thinking` block”이라는 문구를 기준으로 일치시키세요. Claude Code의 자동 제거 및 재시도는 이 문구를 기준으로 합니다. 이 봉투로 응답한 테스트 서버에 연결한 Claude Code 2.1.280은 thinking 블록을 제거하고 재시도했습니다. Kunavo를 통해 직접 오류를 발생시키지는 않았으므로 세션이 여전히 매번 실패하면 새 세션을 시작하세요. 실패한 요청에는 요금이 부과되지 않습니다. 네이티브 엔드포인트가 수정 없이 전달하는 항목은 다음에 나와 있습니다 Messages API 참조.
자주 묻는 질문
“Invalid `signature` in `thinking` block”은 무슨 뜻인가요?
API가 반환된 thinking 블록을 검증하지 못했다는 뜻입니다. 모든 thinking 블록에는 서명이 포함되어 있습니다 — Claude 추론의 암호화된 사본입니다. 해당 서명이 잘리거나 변경되었거나 빈 상태로 반환되었거나, 블록이 Claude에 의해 서명된 적이 없으면 검사가 실패합니다. 일시적인 오류가 아니라 400 오류이므로 같은 요청은 매번 실패합니다.
thinking 블록 서명은 만료되나요?
Anthropic 문서에는 만료에 관한 내용이 없습니다. anthropic-sdk-python 트래커(issue #1598, 2026년 8월)에서 GitHub가 기여자로 표시한 계정의 답변은 서명이 만료되지 않으며, API에 도착한 블록이 반환된 블록과 다를 때 검사가 실패한다고 설명합니다. 이는 문서가 아니라 이슈 댓글입니다. 이전에 작동하던 저장 세션이 이제 실패한다면 저장된 블록이나 블록이 거친 경로를 변경했을 수 있는 요소를 확인하세요. 저장 계층, 프록시 또는 백엔드 전환이 원인일 수 있습니다.
thinking 블록을 그냥 삭제하고 계속할 수 있나요?
예. Anthropic은 재생할 수 없는 저장 세션의 복구 방법으로 이를 제시하며, Claude Code도 서명이 거부되면 이전 thinking을 직접 제거합니다. thinking 및 redacted_thinking 블록을 제거하세요 — 모두 제거하는 것이 가장 간단합니다. 다른 블록은 유지하고 한 번 재시도하세요. 모델은 이전 추론을 잃지만 대화는 잃지 않습니다. 도구 사용을 제외하면 Anthropic 문서상 이전 턴의 thinking을 생략해도 됩니다.
모델이나 제공업체를 전환한 뒤 왜 발생하나요?
Anthropic 문서에 따르면 API에서 Claude 모델 간에 전환하면 새 모델이 읽을 수 없는 블록을 오류 없이 삭제하며, 서명은 Claude API, Amazon Bedrock 및 Google Cloud에서 작동합니다. 그래도 Claude Code는 모델 또는 로그인 전환 후 오래된 서명으로 멈춘 세션을 수정해야 했습니다(2.1.152). 공개 사례에는 Claude가 검증할 수 없는 무언가를 거친 기록이 포함됩니다. 같은 base URL 뒤의 비-Claude 모델, 자체 서명을 작성하는 프록시 또는 서명을 유실한 클라이언트가 그 예입니다. 전환 후 thinking 블록을 한 번 제거하세요.
Claude Code가 이 문제를 자동으로 해결하나요?
최신 버전은 시도합니다. 2.1.152부터 모델 또는 로그인 전환 후 오래된 서명을 제거하며, 이전 thinking 블록 없이 서명 거부를 재시도합니다. 이 재시도는 upstream의 오류 문구를 기준으로 하며, Anthropic의 게이트웨이 가이드에 따르면 오류를 자체 봉투로 감싸는 게이트웨이가 이를 깨뜨릴 수 있습니다. 먼저 claude update를 실행하세요. 한 세션이 여전히 매번 실패하면 새 세션을 시작하세요.
관련 가이드
- Claude API 400 “tool_use ids가 tool_result 블록 없이 발견됨” — 순서 규칙
- Claude Code Router — Claude Code를 모든 모델로 라우팅하거나 라우터를 완전히 건너뛰기
- LLM 스트리밍 오류 — SSE 중단, 멈춘 스트림 및 누락된 사용량
- Claude Code “context_management: Extra inputs are not permitted” — 도착하지 않은 베타 헤더
오류 의미에 대한 자세한 내용은 오류 참조에서 확인할 수 있습니다. 가입 및 인증 가이드를 통해 1분이면 키를 받을 수 있습니다.