Three model-specific causes
1. Sampling parameters on Opus 4.7 and later
Anthropic deprecated temperature, top_p, and top_k on Claude Opus 4.7 and everything after it, Opus 4.8 included. Set any of them to a non-default value and the call fails with a 400 instead of the field being quietly ignored. The fix is removal, not tuning: drop the parameters and steer variability through the prompt.
2. Prefilled assistant messages
Ending the conversation with a partial assistant turn used to be the go-to trick for forcing output shape. Current models reject it. Claude Fable 5, Claude Mythos 5, Claude Mythos Preview, Claude Opus 4.8, Opus 4.7, Opus 4.6, and Sonnet 4.6 all return a 400 with this exact message:
"Prefilling assistant messages is not supported for this model."
Anthropic's docs name three replacements: structured outputs, system-prompt instructions, or output_config.format. If your code starts replies with { to coax out JSON, that's the line to delete.
3. Edited thinking blocks
Extended thinking comes with a strict round-trip rule. If thinking or redacted_thinking blocks in the latest assistant message were edited, reordered, filtered, or reconstructed, the API returns a 400. The message starts with the offending block's position, such as messages.1.content.0, and then states the rule:
`thinking` or `redacted_thinking` blocks in the latest assistant message
cannot be modified. These blocks must remain as they were in the
original response.
With tool use, every thinking block must be passed back exactly as received, including empty ones. History-trimming middleware that strips "useless" blocks to save tokens is the usual culprit here, and it breaks quietly until the first tool call.
Common request-schema causes
Once the three modern traps are cleared, what's left is the original meaning of the error: malformed JSON, a missing required field like model or max_tokens, a wrong type, or a broken message structure. Whatever the trigger, the response rides the same envelope, and the request_id is your ticket number if you end up writing to support:
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "..."
},
"request_id": "req_..."
}
Start with a minimal request
For the most common 2026 case, the entire repair is deleting fields. Before and after for an Opus 4.8 call:
# BEFORE: returns 400 on claude-opus-4-8
{
"model": "claude-opus-4-8",
"max_tokens": 1024,
"temperature": 0.7,
"top_p": 0.9,
"messages": [{"role": "user", "content": "Summarize this contract."}]
}
# AFTER: same call, sampling parameters removed
{
"model": "claude-opus-4-8",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Summarize this contract."}]
}
If the old temperature: 0.2 was there for consistency, say so in the prompt instead — "give the single most likely reading, don't brainstorm alternatives" — and reach for structured outputs when a parser consumes the result.
If you're migrating off Opus 4 or 4.1
Sampling parameters are an easy migration-related cause to miss. Opus 4 retired June 15, 2026, and Opus 4.1 follows August 5. When changing the model ID to claude-opus-4-8, review the request builder in the same change rather than assuming the old temperature setting remains valid. The Opus 4 and 4.1 retirement guide covers the timeline, and the Opus 4.8 pricing page records the new rates.