Skip to content

fix: disable assistant prefill for Claude 4.6 models#14772

Open
hsuanguo wants to merge 4 commits intoanomalyco:devfrom
hsuanguo:fix/github-copilot-claude-prefill-issue-13768
Open

fix: disable assistant prefill for Claude 4.6 models#14772
hsuanguo wants to merge 4 commits intoanomalyco:devfrom
hsuanguo:fix/github-copilot-claude-prefill-issue-13768

Conversation

@hsuanguo
Copy link

@hsuanguo hsuanguo commented Feb 23, 2026

Issue for this PR

Closes #13768

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Problem:
Claude Opus 4.6 and Sonnet 4.6 models reject requests where the last message in the conversation is an assistant message, returning: "This model does not support assistant message prefill. The conversation must end with a user message."

This happens in at least two scenarios:

  1. When OpenCode reaches max steps and appends an assistant message as a hint to the model
  2. When a prior turn was interrupted/aborted mid-session, leaving an assistant message as the last entry in the conversation

The issue affects these models across all providers — native Anthropic API, GitHub Copilot, OpenRouter, etc.

Fix:
Added stripTrailingAssistant() inside normalizeMessages() in provider/transform.ts. Since normalizeMessages is called from the single ProviderTransform.message() choke point used for all outgoing requests, this covers every code path rather than patching individual call sites.

For models that don't support prefill (detected via supportsAssistantPrefill()), any trailing assistant messages are stripped before the request is sent. For all other models, nothing changes.

How did you verify your code works?

Confirmed the root cause using logs from a live session that reproduced the error:

  • providerID=anthropic, modelID=claude-opus-4-6, URL https://api.anthropic.com/v1/messages
  • The last message in the 134-message conversation was role: assistant from a prior interrupted turn — not a max steps prefill
  • This showed the original fix was too narrow (only covered max steps)

Added integration tests in ProviderTransform.message - strip trailing assistant for Claude 4.6 that verify:

  • Trailing assistant message is stripped for Claude 4.6
  • Trailing assistant message is preserved for Claude 3.5 (which supports prefill)
  • Multiple consecutive trailing assistant messages are all stripped
  • No-op when last message is already a user message

Screenshots / recordings

Not applicable - backend logic fix

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Claude Opus 4.6 and Sonnet 4.6 models don't support assistant message
prefill across all providers (Anthropic, GitHub Copilot, OpenRouter, etc),
causing errors when OpenCode reaches max steps.

This fix detects Claude 4.6 models and uses a user message instead of
assistant prefill for max steps handling, while preserving prefill for
models that support it.

Changes:
- Add supportsAssistantPrefill() to detect Claude 4.6 models
- Update max steps handling to conditionally use user/assistant role
- Add comprehensive tests for various providers and model versions

Fixes anomalyco#13768
@github-actions github-actions bot added the needs:compliance This means the issue will auto-close after 2 hours. label Feb 23, 2026
@hsuanguo hsuanguo closed this Feb 23, 2026
@github-actions github-actions bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Feb 23, 2026
@github-actions
Copy link
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

…co#13768)

The original fix only covered the isLastStep/MAX_STEPS prefill case.
Logs revealed the error also occurs in normal conversation flow when
any assistant message ends up last in the message array (e.g. from an
aborted or interrupted turn).

Broader fix: add stripTrailingAssistant() inside normalizeMessages()
which is the single choke point for all message processing. This
strips any trailing assistant messages for models that don't support
prefill (Claude opus-4.6 and sonnet-4.6 across all providers), covering
all code paths rather than just the max steps case.

Also reverts the prompt.ts role switch since normalizeMessages handles
it more correctly at the transport layer.
@adlternative
Copy link

@hsuanguo Has this been fixed yet? This feature is very important to me.

@hsuanguo
Copy link
Author

@hsuanguo Has this been fixed yet? This feature is very important to me.

I haven't seen the error in the last couple of days so I assume it fixes it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

This model does not support assistant message prefill / Github Copilot with Opus 4.6

2 participants