[BUG] Desktop + Bedrock: Haiku 4.5 sent as bare model ID (not inference profile) on Scheduled Task follow-ups → intermittent 400 "invalid model identifier"

Open 💬 5 comments Opened Jun 3, 2026 by rhysmccaig-addepar

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

In Claude for Desktop (Local Agent Mode / Cowork) configured for AWS Bedrock, typing a
follow-up message into a Scheduled Tasks session fails with:

API Error (claude-haiku-4-5-20251001): 400 The provided model identifier is invalid.

The app applies the model to the session via LocalAgentModeSessions.setModel using the bare
model ID claude-haiku-4-5-20251001 instead of the configured Bedrock inference-profile ID
global.anthropic.claude-haiku-4-5-20251001-v1:0. Bedrock rejects the bare ID because in this
account/region Haiku 4.5 is only invokable via an inference profile.

The failures alternate every other follow-up, and the logs show exactly why:

  1. A Haiku follow-up sets the bare ID, then sends → 400.
  2. Immediately after the failure, the app re-sets the qualified profile ID on the session.
  3. The next follow-up therefore runs with the qualified ID → succeeds.
  4. The follow-up after that re-applies the bare ID → 400 again.

This bare↔qualified toggle on each follow-up produces the observed ~50% failure rate.

The bug is specific to Haiku. The exact same follow-up path sends the correctly-qualified profile
ID for Sonnet (global.anthropic.claude-sonnet-4-6) on every turn, and those turns always succeed.

It occurs only when all of these hold:

  1. In the Scheduled Tasks tab (not in normal conversations)
  2. Model is Haiku (Sonnet / Opus are unaffected)
  3. The request is a user follow-up after the scheduled task ran — the scheduled task's own turns

succeed, even across multiple turns

Independent Bedrock confirmation (same role/account/region the app uses):

  • get-inference-profile global.anthropic.claude-haiku-4-5-20251001-v1:0status: ACTIVE
  • converse --model-id global.anthropic.claude-haiku-4-5-20251001-v1:0 → 10/10 OK
  • converse --model-id us.anthropic.claude-haiku-4-5-20251001-v1:0 → OK
  • converse --model-id claude-haiku-4-5-20251001 (the bare ID) →

ValidationException: The provided model identifier is invalid. — matches the app error exactly

So the model is enabled and the profile works; only the bare ID is rejected. The defect is the app
applying the unqualified identifier on this code path for Haiku.

What Should Happen?

On the interactive follow-up / setModel path, when the inference provider is Bedrock, the app
should apply the fully-qualified inference-profile ID
(global.anthropic.claude-haiku-4-5-20251001-v1:0) — exactly as the scheduled-task run path and the
Sonnet path already do — rather than the bare claude-haiku-4-5-20251001. Every Haiku follow-up
should succeed, with no alternating 400s.

Error Messages/Logs

Chronological chain from `~/Library/Logs/Claude-3p/*.log`, single session (IDs redacted as
`XXXX`). Note how `setModel` toggles between the bare and qualified ID, and each turn's outcome
follows the ID that was active when it was sent:


# --- Scheduled task runs: model built from configured list = QUALIFIED -> healthy ---
[CycleHealth] Healthy cycle: { ... model: 'global.anthropic.claude-haiku-4-5-20251001-v1:0', cycle_health: 'healthy' }

# --- Follow-up #1: app sets the BARE id, then sends -> 400 ---
LocalAgentModeSessions.setModel: sessionId=XXXX, model=claude-haiku-4-5-20251001
LocalAgentModeSessions.sendMessage: sessionId=XXXX, ...
[APIError] Intermediate SDK error "model_not_found" for session XXXX — continuing to read stream
[Result] Turn failed for session XXXX: subtype=success, is_error=true
[CycleHealth] Unhealthy cycle: {
  ... model: 'claude-haiku-4-5-20251001', cycle_health: 'unhealthy', unhealthy_reason: 'api_error',
  error_message: 'API Error (claude-haiku-4-5-20251001): 400 The provided model identifier is invalid..' }

# --- App re-sets the QUALIFIED id right after the failure ---
LocalAgentModeSessions.setModel: sessionId=XXXX, model=global.anthropic.claude-haiku-4-5-20251001-v1:0

# --- Follow-up #2: inherits the QUALIFIED id -> healthy ---
LocalAgentModeSessions.sendMessage: sessionId=XXXX, ...
[CycleHealth] Healthy cycle: { ... model: 'global.anthropic.claude-haiku-4-5-20251001-v1:0', cycle_health: 'healthy' }

# --- Follow-up #3: app sets the BARE id again -> 400 (same as #1) ---
LocalAgentModeSessions.setModel: sessionId=XXXX, model=claude-haiku-4-5-20251001
[CycleHealth] Unhealthy cycle: {
  ... model: 'claude-haiku-4-5-20251001', unhealthy_reason: 'api_error',
  error_message: 'API Error (claude-haiku-4-5-20251001): 400 The provided model identifier is invalid..' }
LocalAgentModeSessions.setModel: sessionId=XXXX, model=global.anthropic.claude-haiku-4-5-20251001-v1:0   # re-set qualified again

# --- Switch to Sonnet: follow-up path uses the QUALIFIED id, every turn -> healthy ---
LocalAgentModeSessions.setModel: sessionId=XXXX, model=global.anthropic.claude-sonnet-4-6
[CycleHealth] Healthy cycle: { ... model: 'global.anthropic.claude-sonnet-4-6', cycle_health: 'healthy' }
LocalAgentModeSessions.sendMessage: sessionId=XXXX, ...
[CycleHealth] Healthy cycle: { ... model: 'global.anthropic.claude-sonnet-4-6', cycle_health: 'healthy' }


Per-turn summary of the same session (the `setModel` value is what was active when each turn was
sent; the post-failure re-set to the qualified ID is what lets the *next* turn succeed):

| Turn | Trigger | `setModel` (active when sent) | `CycleHealth.model` | Result |
|------|---------|-------------------------------|---------------------|--------|
| Scheduled run | task | `global.…haiku…-v1:0` (from config) | `global.…haiku…-v1:0` | ✅ healthy |
| Follow-up #1 | user | `claude-haiku-4-5-20251001` (bare) | `claude-haiku-4-5-20251001` | ❌ 400 |
| Follow-up #2 | user | `global.…haiku…-v1:0` (re-set after #1) | `global.…haiku…-v1:0` | ✅ healthy |
| Follow-up #3 | user | `claude-haiku-4-5-20251001` (bare) | `claude-haiku-4-5-20251001` | ❌ 400 |
| Follow-up #4 | user | `global.…haiku…-v1:0` (re-set after #3) | `global.…haiku…-v1:0` | ✅ healthy |
| Switch to Sonnet | user | `global.anthropic.claude-sonnet-4-6` | `global.anthropic.claude-sonnet-4-6` | ✅ healthy |
| Sonnet follow-up | user | `global.anthropic.claude-sonnet-4-6` (retained) | `global.anthropic.claude-sonnet-4-6` | ✅ healthy |

Steps to Reproduce

Prerequisites: Claude for Desktop configured for AWS Bedrock, in a region where Haiku 4.5 requires an
inference profile (e.g. us-west-2), with the model list specifying the qualified profile IDs:
global.anthropic.claude-haiku-4-5-20251001-v1:0, global.anthropic.claude-sonnet-4-6,
global.anthropic.claude-opus-4-6-v1.

  1. Create a Scheduled Task and set its model to Haiku 4.5.
  2. Let the scheduled task run (it succeeds, even over multiple turns).
  3. In that scheduled-task session, send a follow-up message → it fails with

API Error (claude-haiku-4-5-20251001): 400 The provided model identifier is invalid.

  1. Send another follow-up → it succeeds.
  2. Send another follow-up → it fails again. (Failures alternate every other follow-up.)
  3. In the same session, switch the model to Sonnet and send follow-ups → all succeed.
  4. Inspect ~/Library/Logs/Claude-3p/main.log: failing turns are preceded by

setModel ... model=claude-haiku-4-5-20251001 (bare); after each failure the app re-sets
setModel ... model=global.anthropic.claude-haiku-4-5-20251001-v1:0, which is why the next turn
succeeds. Sonnet turns always use the qualified global.anthropic.… ID.

Claude Model

Not sure / Multiple models

Is this a regression?

I don't know

Last Working Version

n/a

Claude Code Version

Claude for Desktop 1.10628.0 (bundled claude-code SDK 2.1.160)

Platform

AWS Bedrock

Operating System

macOS

Terminal/Shell

Other

Additional Information

Possible Root cause: On the interactive follow-up path in Local Agent Mode, setModel applies the bare
Haiku ID claude-haiku-4-5-20251001 to the session instead of the configured Bedrock
inference-profile ID global.anthropic.claude-haiku-4-5-20251001-v1:0, so the turn 400s. After the
failure the app re-sets the qualified ID on the session — so the next follow-up succeeds, then the
following follow-up re-applies the bare ID and fails again. This bare↔qualified toggle is what
produces the alternating fail/succeed (50%) pattern. Sonnet/Opus are applied with the qualified ID
on every turn, which is why the bug is Haiku-specific. The scheduled task's own turns build the model
from the configured model list and are unaffected.

Suggested fix: On the setModel / interactive follow-up code path, when the provider is Bedrock,
apply the fully-qualified inference-profile ID from the configured model list (as the scheduled-run paths already do) rather than a stripped/bare model name — and don't toggle back to the bare ID on subsequent follow-ups.

Workarounds:

  • Switch the scheduled-task follow-up conversation to Sonnet (and optionally back to Haiku).
  • For Haiku, the every-other-turn failure can be worked around by resending, but the scheduled task

itself runs fine regardless.

Notes:

  • The managed/configured model list is correct (qualified global. profile IDs); no user config

overrides the model. The bare ID is applied by the app, not read from any config.

  • Sensitive identifiers (AWS account ID, SSO details, session IDs, tokens) have been redacted as

XXXX.

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗