zeroclaw-labs/zeroclaw · error

No IAM role attached to this instance

Error message

No IAM role attached to this instance

What it means

The Bedrock provider's from_imds credential path queries EC2 instance metadata (169.254.169.254) for the IAM security-credentials role list. The IMDS endpoint responded (with a valid token), but the role list came back empty, meaning no instance profile is attached, so no credentials can be derived from the instance.

Source

Thrown at crates/zeroclaw-providers/src/bedrock.rs:235

        // Step 1: get IMDSv2 token
        let token = client
            .put("http://169.254.169.254/latest/api/token")
            .header("X-aws-ec2-metadata-token-ttl-seconds", "21600")
            .send()
            .await?
            .text()
            .await?;

        // Step 2: get IAM role name
        let role = client
            .get("http://169.254.169.254/latest/meta-data/iam/security-credentials/")
            .header("X-aws-ec2-metadata-token", &token)
            .send()
            .await?
            .text()
            .await?;
        let role = role.trim().to_string();
        anyhow::ensure!(!role.is_empty(), "No IAM role attached to this instance");

        // Step 3: get credentials for that role
        let creds_url = format!(
            "http://169.254.169.254/latest/meta-data/iam/security-credentials/{}",
            role
        );
        let creds_json: serde_json::Value = client
            .get(&creds_url)
            .header("X-aws-ec2-metadata-token", &token)
            .send()
            .await?
            .json()
            .await?;

        let access_key_id = creds_json["AccessKeyId"]
            .as_str()
            .ok_or_else(|| {
                ::zeroclaw_log::record!(

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Attach an IAM instance profile whose role has Bedrock permissions to the instance, then re-run
  2. For containers on EC2, raise the metadata hop limit: aws ec2 modify-instance-metadata-options --instance-id i-... --http-put-response-hop-limit 2
  3. Provide explicit credentials instead (AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY or a named profile) and skip IMDS

Example fix

# before: instance without profile
aws ec2 associate-iam-instance-profile \
  --instance-id i-1234 \
  --iam-instance-profile Name=bedrock-runner-role
Defensive patterns

Strategy: fallback

Validate before calling

# probe IMDS for an attached role before relying on it
TOKEN=$(curl -sf -X PUT http://169.254.169.254/latest/api/token -H 'X-aws-ec2-metadata-token-ttl-seconds: 60') && \
ROLE=$(curl -sf http://169.254.169.254/latest/meta-data/iam/security-credentials/ -H "X-aws-ec2-metadata-token: $TOKEN") && \
[ -n "$ROLE" ] || echo 'no instance profile — attach one or use explicit credentials' >&2

Try / catch

when constructing the Bedrock provider, try IMDS credentials; on the no-IAM-role error fall back to explicit credentials (environment/profile) before giving up, and log which path succeeded

Prevention

When it happens

Trigger: EC2 (or ECS/ECR-based) workload launched without an IAM instance profile; the role was attached in IAM but not as an instance profile on the instance; containers where the metadata hop limit prevents reaching the credentials path so only an empty role list is visible; a non-AWS environment where something else answers on 169.254.169.254.

Common situations: Terraform/CloudFormation templates that create the role but forget the instance-profile association; containers on EC2 needing --http-put-response-hop-limit 2; developers assuming AWS_* env-var-less code will just work on a bare instance.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/d1f9095622a1952f. Report an issue: GitHub.