{"record":{"id":"62c015f7b5fa15a9","repo":"JuliusBrussee/caveman","slug":"awscreds-s-http-d","errorCode":null,"errorMessage":"awscreds: %s: http %d","messagePattern":"awscreds: (.+?): http (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/awscreds/awscreds.go","lineNumber":613,"sourceCode":"\t}\n\treq.Header.Set(\"X-aws-ec2-metadata-token\", token)\n\treturn p.doJSON(p.link, req, what)\n}\n\n// doJSON performs one attempt and returns the bounded body. A non-2xx response\n// is reported by status only: a metadata body holds credential material.\nfunc (p *Provider) doJSON(client *http.Client, req *http.Request, what string) ([]byte, error) {\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"awscreds: %s request failed: %w\", what, err)\n\t}\n\tdefer resp.Body.Close()\n\tbody, err := io.ReadAll(io.LimitReader(resp.Body, maxBody))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"awscreds: read %s response: %w\", what, err)\n\t}\n\tif resp.StatusCode < 200 || resp.StatusCode > 299 {\n\t\treturn nil, fmt.Errorf(\"awscreds: %s: http %d\", what, resp.StatusCode)\n\t}\n\treturn body, nil\n}\n\nfunc credentialsFromJSON(body []byte, source string) (*result, error) {\n\tvar parsed credentialJSON\n\tif err := json.Unmarshal(body, &parsed); err != nil {\n\t\treturn nil, fmt.Errorf(\"awscreds: %s returned an unparseable response\", source)\n\t}\n\tif parsed.Code != \"\" && !strings.EqualFold(parsed.Code, \"Success\") {\n\t\treturn nil, fmt.Errorf(\"awscreds: %s returned code %q\", source, parsed.Code)\n\t}\n\texpires, err := parseExpiry(parsed.Expiration)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"awscreds: %s credential expiry: %w\", source, err)\n\t}\n\treturn &result{\n\t\tcreds: awssig.Credentials{","sourceCodeStart":595,"sourceCodeEnd":631,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/awscreds/awscreds.go#L595-L631","documentation":"doJSON performs one HTTP attempt against an AWS credential endpoint (ECS container metadata or IMDS) and returns the response body only when the status is 2xx. When the endpoint answers with any non-2xx status (404, 403, 500, etc.), it aborts with this error, deliberately reporting only the numeric status because a metadata response body can contain credential material. It is a generic HTTP status failure from the AWS metadata service.","triggerScenarios":"Calling fromContainer when AWS_CONTAINER_CREDENTIALS_RELATIVE_URI points at a wrong/nonexistent path (404); calling fromIMDS or imdsGet when the EC2 instance has no attached IAM role (404 on the security-credentials path), the IMDSv2 token request is rejected (403), or the metadata service returns 5xx; also raised for the imds token PUT when IMDS is throttled or disabled.","commonSituations":"Running outside ECS/E2 where the metadata env vars are set incorrectly; an EC2 instance whose IAM instance profile was detached after boot; IMDS hop limit or token endpoint misconfigured; IMDS disabled via instance metadata options (returns 403/404); proxy or security software interfering with 169.254.169.254.","solutions":["Identify which 'what' (imds token, imds role, imds credentials, container metadata) failed from the message and check the corresponding endpoint: verify AWS_CONTAINER_CREDENTIALS_RELATIVE_URI or the IMDS base (AWS_EC2_METADATA_SERVICE_ENDPOINT).","For 'imds credentials: http 404', attach an IAM instance profile to the EC2 instance (aws ec2 associate-iam-instance-profile) or pick a role listed at /latest/meta-data/iam/security-credentials/.","For http 403/404 on the token request, confirm IMDSv2 is enabled in the instance metadata options and no firewall blocks 169.254.169.254.","For 5xx, retry after a short delay; metadata services throttle briefly.","If running in a non-AWS environment (local dev, other clouds), stop relying on metadata credentials and supply explicit credentials."],"exampleFix":"// before\ncreds, err := provider.Credentials(ctx) // fails: awscreds: imds credentials: http 404\n// after\n// ensure the instance has a role:\n//   aws ec2 associate-iam-instance-profile --instance-id i-123 --iam-instance-profile Name=my-profile\ncreds, err := provider.Credentials(ctx)","handlingStrategy":"retry","validationCode":"// best-effort precheck\nif u := os.Getenv(\"AWS_EC2_METADATA_SERVICE_ENDPOINT\"); u == \"\" && os.Getenv(\"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI\") == \"\" {\n    // may still be EC2 IMDS; nothing to precheck client-side\n}","typeGuard":null,"tryCatchPattern":"creds, err := provider.Credentials(ctx)\nif err != nil {\n    if strings.Contains(err.Error(), \"http 4\") {\n        // misconfiguration (no role / bad path): do not retry, fix IAM or env\n    } else if strings.Contains(err.Error(), \"http 5\") {\n        // transient: retry with backoff\n    }\n    return fmt.Errorf(\"aws credential lookup: %w\", err)\n}","preventionTips":["Attach an IAM instance profile/task role before deploying so the metadata paths exist.","Add NO_PROXY=169.254.169.254 so proxies never intercept metadata traffic.","Verify IMDSv2 is enabled in instance metadata options.","Distinguish 4xx (config) from 5xx (transient) in your error handling."],"tags":["aws","http","metadata-service","credentials"],"backgroundTag":"http-error-response","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}