warpdotdev/warp · error · anyhow::Error

Multiple API keys match '{key_identifier}'; specify the key

Error message

Multiple API keys match '{key_identifier}'; specify the key by UID

What it means

`resolve_api_key_identifier` found two or more API keys whose name equals the identifier. In a TTY it shows an interactive `Select` picker; with non-interactive stdin it prints every match and errors, requiring the unique UID instead. Name-based selection is intentionally refused when it would be ambiguous.

Source

Thrown at app/src/ai/agent_sdk/api_key.rs:345

    if io::stdin().is_terminal() {
        return match Select::new(
            &format!("Multiple API keys match '{key_identifier}'. Select a key to expire:"),
            matches,
        )
        .prompt()
        {
            Ok(key) => Ok(Some(key)),
            Err(InquireError::OperationCanceled | InquireError::OperationInterrupted) => Ok(None),
            Err(err) => Err(err.into()),
        };
    }
    println!("Multiple API keys match '{key_identifier}':");
    for key in matches {
        println!("  {key}");
    }

    Err(anyhow!(
        "Multiple API keys match '{key_identifier}'; specify the key by UID"
    ))
}

#[derive(Debug, Clone, Serialize)]
struct CreatedApiKeyInfo {
    raw_api_key: String,
    api_key: ApiKeyInfo,
}

#[derive(Debug, Clone, Serialize)]
struct ExpiredApiKeyInfo {
    key_uid: String,
    expired: bool,
}

fn sort_api_keys(
    keys: &mut [ApiKeyInfo],

View on GitHub (pinned to e72fd7aacb)

Solutions

  1. Copy the UID of the intended key from the printed list (or `warp api-key list`) and pass that instead
  2. Run the command in a real terminal and choose from the interactive selector
  3. Rename or expire duplicate-named keys so the name becomes unique

Example fix

# before
warp api-key expire ci-key < /dev/null
# after
warp api-key list   # note the uid
warp api-key expire <uid-from-list>
Defensive patterns

Strategy: validation

Validate before calling

fn unique_name_match<'a>(keys: &'a [ApiKeyInfo], name: &str) -> Option<&'a ApiKeyInfo> {
    let mut matches = keys.iter().filter(|k| k.name == name);
    let first = matches.next()?;
    matches.next().is_none().then_some(first)
}
// When None, fall back to UID lookup instead of letting the CLI error.

Prevention

When it happens

Trigger: Running `warp api-key expire <name>` where more than one listed key shares that name AND stdin is not a terminal, so the interactive selector cannot be shown.

Common situations: Automation scripts referring to keys by a reused name like 'ci-key'; teams creating same-named keys over time; piping commands so the picker never appears; CI jobs using names instead of UIDs.

Related errors


AI-assisted analysis of warpdotdev/warp@e72fd7aacb (2026-08-16). Data as JSON: /api/errors/660de85dd78e2b6e. Report an issue: GitHub.