Skip to content

fix: default to first-party model alias when none specified (#1416)#1432

Open
farmer-data wants to merge 1 commit into
anthropics:mainfrom
farmer-data:fix/default-model-1416
Open

fix: default to first-party model alias when none specified (#1416)#1432
farmer-data wants to merge 1 commit into
anthropics:mainfrom
farmer-data:fix/default-model-1416

Conversation

@farmer-data

Copy link
Copy Markdown
Contributor

Fixes #1416

Problem

When no model is specified, the action passes model: undefined all the way through to the Agent SDK, so the SDK/CLI falls back to its own bundled default model. In the currently-pinned version that resolves to the retired claude-sonnet-4-20250514, producing:

API Error: 404 {"type":"error","error":{"type":"not_found_error","message":"model: claude-sonnet-4-20250514"}}

Nothing in this repo hardcodes the bad id — it's inherited from the pinned SDK/CLI default, so it broke silently when that snapshot was retired server-side. With an OAuth token the 404 retries until the job timeout, so the run never completes. Every consumer currently has to add --model to their workflow by hand to avoid it.

How I solved it

Flow that produced the bug:

  • action.yml defines no model input and never exports ANTHROPIC_MODEL.
  • src/entrypoints/run.tsrunClaude(..., { model: process.env.ANTHROPIC_MODEL })undefined
  • base-action/src/parse-sdk-options.tssdkOptions.model = options.model (undefined)
  • base-action/src/run-claude-sdk.tsquery({ options }) → SDK supplies its stale default

The fix sets an explicit default in parseSdkOptions via a new resolveModel() helper. Key decisions:

  • Use a model alias ("sonnet"), not a dated snapshot. The alias resolves server-side to the current model, so the action can't rot the same way a pinned id did.
  • Preserve precedence. Explicit options.model wins → then --model in claudeArgs (kept in extraArgs and passed to the CLI, so we deliberately return undefined to avoid specifying the model twice) → then the default alias.
  • Gate to the first-party provider. The default is skipped when CLAUDE_CODE_USE_BEDROCK / CLAUDE_CODE_USE_VERTEX / CLAUDE_CODE_USE_FOUNDRY is set, since "sonnet" isn't a valid Bedrock/Vertex/Foundry model id — those providers resolve their own default.

After this, users no longer need per-repo --model workarounds.

Tests

Added a model defaulting suite in base-action/test/parse-sdk-options.test.ts (env-isolated to avoid provider-var leakage):

  • no model → defaults to "sonnet"
  • explicit options.model preserved (and trimmed)
  • --model in claudeArgs still overrides; sdkOptions.model stays undefined
  • Bedrock / Vertex / Foundry → no alias injected
  • explicit model preserved even for third-party providers

All 761 tests pass; tsc --noEmit and prettier --check are clean.

🤖 Generated with Claude Code

…cs#1416)

When no model was specified, the action passed model: undefined through
to the Agent SDK, which fell back to its bundled default snapshot. In the
currently-pinned version that resolves to the retired
claude-sonnet-4-20250514, producing a 404 not_found_error and (with an
OAuth token) retrying until the job timeout.

Set an explicit default in parseSdkOptions using the "sonnet" alias
(resolved server-side to the current snapshot) so the action never
inherits a stale SDK/CLI default. Precedence is preserved: an explicit
options.model wins, then --model in claudeArgs (extraArgs), then the
default. The default is gated to the first-party provider and skipped for
Bedrock/Vertex/Foundry, whose model id formats make a first-party alias
invalid.

Fixes anthropics#1416

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@farmer-data farmer-data force-pushed the fix/default-model-1416 branch from 65cd8bd to 1f0468f Compare June 24, 2026 23:43
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.

Action uses non-existent model when no model is specified then fails

1 participant