warpdotdev/warp · error

STS AssumeRoleWithWebIdentity failed: {detail}

Error message

STS AssumeRoleWithWebIdentity failed: {detail}

What it means

Same STS AssumeRoleWithWebIdentity failure, but on the credential refresh path in bedrock_credentials.rs: it runs when stored Bedrock credentials near expiry and exchanges a web identity token for fresh STS credentials before updating ApiKeyManager (step 3). A failed refresh leaves the manager on the old credentials.

Source

Thrown at app/src/ai/bedrock_credentials.rs:84

    let client = sts_client(region).await;
    let session_name = aws_role_session_name(task_id);
    let sts_creds = client
        .assume_role_with_web_identity()
        .role_arn(role_arn)
        .role_session_name(&session_name)
        .web_identity_token(&token.token)
        .send()
        .await
        .map_err(|err| {
            let detail = err
                .as_service_error()
                .map(|e| e.to_string())
                .unwrap_or_else(|| err.to_string());
            report_error!(
                anyhow::Error::new(err)
                    .context("Bedrock OIDC refresh: STS AssumeRoleWithWebIdentity error")
            );
            anyhow::anyhow!("STS AssumeRoleWithWebIdentity failed: {detail}")
        })?
        .credentials
        .context("STS response did not include credentials")?;

    let aws_creds = AwsCredentials::new(
        sts_creds.access_key_id().to_string(),
        sts_creds.secret_access_key().to_string(),
        Some(sts_creds.session_token().to_string()),
        SystemTime::try_from(*sts_creds.expiration()).ok(),
    );

    // Step 3: Update ApiKeyManager with the fresh credentials.
    foreground
        .spawn(move |_, ctx| {
            ApiKeyManager::handle(ctx).update(ctx, |manager, ctx| {
                manager.set_aws_credentials_state(
                    AwsCredentialsState::Loaded {
                        credentials: aws_creds,

View on GitHub (pinned to e72fd7aacb)

Solutions

  1. On InvalidIdentityToken-class failures, force a full Bedrock OIDC re-login instead of retrying refresh
  2. Trigger refresh earlier, before the web identity token's expiry rather than near it
  3. Add bounded retry with backoff for throttling/transient errors
  4. Verify system clock sync (NTP) on machines showing repeated refresh failures
Defensive patterns

Strategy: retry

Validate before calling

if token_near_expiry(&oidc_token, margin) {
    reauthenticate_oidc().await?; // refresh cannot succeed with a stale token
}

Try / catch

match refresh_credentials(&token).await {
    Err(e) if e.to_string().contains("STS AssumeRoleWithWebIdentity failed") => {
        if is_invalid_token(&e) {
            force_full_relogin().await // refresh path is unrecoverable with bad token
        } else {
            with_backoff(|| refresh_credentials(&token)).await // throttling/transient
        }
    }
    r => r,
}

Prevention

When it happens

Trigger: The refresh flow's assume_role_with_webidentity().send() errors: stale OIDC token (long session or clock skew), role/provider changed since login, throttling, or transient STS/network errors (bedrock_credentials.rs:78-88).

Common situations: Refresh scheduled too close to token expiry so the token is already invalid; system clock skew; user's role was removed; intermittent STS availability during refresh windows.

Related errors


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