zed-industries/zed · error · anyhow::Error

invalid model id {id}

Error message

invalid model id {id}

What it means

`ConverseModel::from_id` maps a model id string to a Bedrock model variant, but only recognizes `claude-*` ids via `starts_with` prefixes (claude-fable-5, claude-opus-5, claude-opus-4-x, claude-sonnet-5/4-x, claude-haiku-4-5). Anything else — ARNs (`arn:aws:bedrock:...`), inference-profile ids (`us.anthropic.claude-...`), or non-Claude ids like `llama-4-scout-17b` even though the enum supports them — bails with 'invalid model id'.

Source

Thrown at crates/bedrock/src/models.rs:268

            Ok(Self::ClaudeOpus4_7)
        } else if id.starts_with("claude-opus-4-6") {
            Ok(Self::ClaudeOpus4_6)
        } else if id.starts_with("claude-opus-4-5") {
            Ok(Self::ClaudeOpus4_5)
        } else if id.starts_with("claude-opus-4-1") {
            Ok(Self::ClaudeOpus4_1)
        } else if id.starts_with("claude-sonnet-5") {
            Ok(Self::ClaudeSonnet5)
        } else if id.starts_with("claude-sonnet-4-6") {
            Ok(Self::ClaudeSonnet4_6)
        } else if id.starts_with("claude-sonnet-4-5") {
            Ok(Self::ClaudeSonnet4_5)
        } else if id.starts_with("claude-sonnet-4") {
            Ok(Self::ClaudeSonnet4)
        } else if id.starts_with("claude-haiku-4-5") {
            Ok(Self::ClaudeHaiku4_5)
        } else {
            anyhow::bail!("invalid model id {id}");
        }
    }

    pub fn id(&self) -> &str {
        match self {
            Self::ClaudeFable5 => "claude-fable-5",
            Self::ClaudeOpus5 => "claude-opus-5",
            Self::ClaudeOpus4_8 => "claude-opus-4-8",
            Self::ClaudeOpus4_7 => "claude-opus-4-7",
            Self::ClaudeOpus4_6 => "claude-opus-4-6",
            Self::ClaudeOpus4_5 => "claude-opus-4-5",
            Self::ClaudeOpus4_1 => "claude-opus-4-1",
            Self::ClaudeSonnet5 => "claude-sonnet-5",
            Self::ClaudeSonnet4_6 => "claude-sonnet-4-6",
            Self::ClaudeSonnet4_5 => "claude-sonnet-4-5",
            Self::ClaudeSonnet4 => "claude-sonnet-4",
            Self::ClaudeHaiku4_5 => "claude-haiku-4-5",
            Self::Llama4Scout17B => "llama-4-scout-17b",

View on GitHub (pinned to f4178619ac)

Solutions

  1. Use the bare prefix form the parser accepts, e.g. `claude-sonnet-4-5` or `claude-sonnet-4-5-20250929` (suffix after the matched prefix is fine).
  2. For non-Claude or profile-id models, configure them via the `custom` model entry in Bedrock settings (name/max_tokens fields) instead of relying on `from_id`.
  3. Double-check spelling — the matcher is literal `starts_with`, so `anthropic.claude-...` fails.
  4. If embedding in your own code, validate ids against `from_id` at config-load time and reject early with the list of valid prefixes.

Example fix

// before: full Bedrock inference-profile id or ARN fails
let model = ConverseModel::from_id("us.anthropic.claude-sonnet-4-5-20241022-v1:0")?; // invalid model id

// after: bare id prefix, or route exotic ids through Custom
let model = ConverseModel::from_id("claude-sonnet-4-5")?;
// or, for models from_id does not know:
let model = ConverseModel::Custom { name: profile_id.into(), max_tokens: 8192, display_name: None, max_output_tokens: None, default_temperature: None, cache_configuration: None };
Defensive patterns

Strategy: validation

Validate before calling

// Validate at settings-load time, not on first request
for id in &configured_ids {
    if let Err(err) = ConverseModel::from_id(id) {
        return Err(anyhow!("bedrock settings: {err:#}; use a claude-* prefix id or a custom entry"));
    }
}

Type guard

fn is_known_converse_model(id: &str) -> bool {
    [
        "claude-fable-5", "claude-opus-5", "claude-opus-4-8", "claude-opus-4-7",
        "claude-opus-4-6", "claude-opus-4-5", "claude-opus-4-1", "claude-sonnet-5",
        "claude-sonnet-4-6", "claude-sonnet-4-5", "claude-sonnet-4", "claude-haiku-4-5",
    ]
    .iter()
    .any(|prefix| id.starts_with(prefix))
}

Try / catch

let model = match ConverseModel::from_id(id) {
    Ok(model) => model,
    Err(_) if is_custom_config(id) => ConverseModel::Custom { name: id.into(), max_tokens: 8192, display_name: None, max_output_tokens: None, default_temperature: None, cache_configuration: None },
    Err(err) => return Err(err),
};

Prevention

When it happens

Trigger: Calling `ConverseModel::from_id` with: a full Bedrock model ARN; a regional/global inference profile id such as `us.anthropic.claude-sonnet-4-5-...` (does not start with `claude-`); a non-Claude id like `llama-4-scout-17b` or `gemma-3-12b`; a typo like `claude-sonet-4-5`. Commonly reached from Zed settings listing Bedrock `available_models`.

Common situations: Copying model identifiers from the AWS Bedrock console (which shows profile ids like `us.anthropic...`) into Zed settings; configuring Llama/Nova models through a path that funnels into `from_id`; version-suffix mismatches; settings written for an older/newer Zed with different supported ids.

Related errors


AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20). Data as JSON: /api/errors/c69d10bd7a218aac. Report an issue: GitHub.