{"record":{"id":"b4e34ea51593d475","repo":"JuliusBrussee/caveman","slug":"awscreds-build-s-request-w","errorCode":null,"errorMessage":"awscreds: build %s request: %w","messagePattern":"awscreds: build (.+?) request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/awscreds/awscreds.go","lineNumber":594,"sourceCode":"\t\t\trole = line\n\t\t\tbreak\n\t\t}\n\t}\n\tif role == \"\" {\n\t\treturn nil, errors.New(\"awscreds: no instance profile role attached\")\n\t}\n\n\tcredBody, err := p.imdsGet(ctx, base+\"/latest/meta-data/iam/security-credentials/\"+url.PathEscape(role), token, \"imds credentials\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn credentialsFromJSON(credBody, \"imds\")\n}\n\nfunc (p *Provider) imdsGet(ctx context.Context, endpoint, token, what string) ([]byte, error) {\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"awscreds: build %s request: %w\", what, err)\n\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 {","sourceCodeStart":576,"sourceCodeEnd":612,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/awscreds/awscreds.go#L576-L612","documentation":"imdsGet wraps an error from http.NewRequestWithContext when building one of the two IMDS metadata GETs (role name, then credentials), labeled by the what parameter (e.g. \"imds role\", \"imds credentials\"). The library throws this when the endpoint URL is unparseable or the context is already dead.","triggerScenarios":"The role-name or credentials URL derived from the IMDS base (base + /latest/meta-data/iam/security-credentials/...) is malformed, or ctx was canceled between the token fetch and the GET.","commonSituations":"Endpoint env var with trailing slash handled but other junk characters present; context timeout fired mid-sequence; custom endpoint missing scheme.","solutions":["Inspect the wrapped %w cause: fix net/url parse errors by correcting the endpoint; fix context errors by increasing the timeout.","Set AWS_EC2_METADATA_SERVICE_ENDPOINT to a plain absolute http(s) URL with no extra path junk.","Reuse a single healthy context with sufficient deadline for the whole IMDS sequence.","Fall back to the default endpoint by unsetting the env var."],"exampleFix":"// before\nctx, cancel := context.WithTimeout(ctx, time.Microsecond) // dead before GETs\n// after\nctx, cancel := context.WithTimeout(ctx, 5*time.Second)","handlingStrategy":"try-catch","validationCode":"deadline, ok := ctx.Deadline()\nif !ok || time.Until(deadline) < 2*time.Second {\n    return errors.New(\"context deadline too tight for IMDS token+get sequence\")\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    var urlErr *url.Error\n    if errors.As(err, &urlErr) && errors.Is(urlErr.Err, context.DeadlineExceeded) {\n        // retry with a fresh, longer-lived context\n    }\n}","preventionTips":["Use one context with adequate budget for the full token+role+creds sequence","Don't reuse an already-canceled context across provider calls","Keep the endpoint env var free of control characters"],"tags":["aws","imds","http-client","context-timeout"],"backgroundTag":"invalid-url-format","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"}