{"record":{"id":"0cf49dd9fb5d35b0","repo":"VictoriaMetrics/VictoriaMetrics","slug":"cannot-create-request-for-imdsv2-session-token-at","errorCode":null,"errorMessage":"cannot create request for IMDSv2 session token at url %q: %w","messagePattern":"cannot create request for IMDSv2 session token at url %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/awsapi/config.go","lineNumber":468,"sourceCode":"// MetadataSecurityCredentials represents credentials obtained from http://169.254.169.254/latest/meta-data/iam/security-credentials/*\n//\n// See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html\ntype MetadataSecurityCredentials struct {\n\tAccessKeyID     string    `json:\"AccessKeyId\"`\n\tSecretAccessKey string    `json:\"SecretAccessKey\"`\n\tToken           string    `json:\"Token\"`\n\tExpiration      time.Time `json:\"Expiration\"`\n}\n\n// getMetadataByPath returns instance metadata by url path\nfunc getMetadataByPath(client *http.Client, apiPath string) ([]byte, error) {\n\t// See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html\n\n\t// Obtain session token\n\tsessionTokenURL := \"http://169.254.169.254/latest/api/token\"\n\treq, err := http.NewRequest(http.MethodPut, sessionTokenURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot create request for IMDSv2 session token at url %q: %w\", sessionTokenURL, err)\n\t}\n\treq.Header.Set(\"X-aws-ec2-metadata-token-ttl-seconds\", \"60\")\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot obtain IMDSv2 session token from %q: %w\", sessionTokenURL, err)\n\t}\n\ttoken, err := readResponseBody(resp, sessionTokenURL)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot read IMDSv2 session token from %q: %w\", sessionTokenURL, err)\n\t}\n\n\t// Use session token in the request.\n\tapiURL := \"http://169.254.169.254/latest/\" + apiPath\n\treq, err = http.NewRequest(http.MethodGet, apiURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot create request to %q: %w\", apiURL, err)\n\t}\n\treq.Header.Set(\"X-aws-ec2-metadata-token\", string(token))","sourceCodeStart":450,"sourceCodeEnd":486,"githubUrl":"https://github.com/VictoriaMetrics/VictoriaMetrics/blob/5079fb58f1e8e62113f90c945ad71586c797d770/lib/awsapi/config.go#L450-L486","documentation":"This error is wrapped when http.NewRequest fails to construct the PUT request that fetches an IMDSv2 session token from the EC2 instance metadata endpoint (http://169.254.169.254/latest/api/token). getMetadataByPath builds this request before contacting the metadata service; if the request object itself cannot be created, the library wraps the underlying error. In practice this almost always indicates an invalid URL or method passed to http.NewRequest, which for the hard-coded session token URL is extremely rare.","triggerScenarios":"http.NewRequest(http.MethodPut, \"http://169.254.169.254/latest/api/token\", nil) returns an error — e.g. an unparsable URL or unsupported method. With the hard-coded URL/method this only happens via exotic failures (e.g. url.Parse misbehavior from corrupted builds or custom RoundTripper/test harnesses injecting a different URL).","commonSituations":"Custom test stubs or forked code that parameterize the metadata URL with a malformed value; go-http internals failing on an invalid net/url; virtually never seen in production with the stock URL.","solutions":["Verify the session token URL is the stock value (http://169.254.169.254/latest/api/token) and was not modified or templated incorrectly","Unwrap the %w error (errors.Unwrap / errors.As on *url.Error) to see the root cause from net/url","Check for custom forks/patches of lib/awsapi that altered the URL construction","If seen in tests, fix the test harness that substitutes the metadata endpoint URL"],"exampleFix":"// before\nsessionTokenURL := os.Getenv(\"IMDS_URL\") // may be empty/malformed\nreq, err := http.NewRequest(http.MethodPut, sessionTokenURL, nil)\n// after\nsessionTokenURL := \"http://169.254.169.254/latest/api/token\"\nif u, perr := url.Parse(sessionTokenURL); perr != nil || u.Host == \"\" {\n    return nil, fmt.Errorf(\"invalid IMDS URL %q\", sessionTokenURL)\n}\nreq, err := http.NewRequest(http.MethodPut, sessionTokenURL, nil)","handlingStrategy":"try-catch","validationCode":"// Run before calling config resolution that may hit IMDS\nfunc canBuildTokenRequest() error {\n    _, err := http.NewRequest(http.MethodPut, \"http://169.254.169.254/latest/api/token\", nil)\n    return err\n}","typeGuard":null,"tryCatchPattern":"cfg, err := awsapi.NewConfig()\nif err != nil {\n    if strings.Contains(err.Error(), \"cannot create request for IMDSv2 session token\") {\n        var urlErr *url.Error\n        if errors.As(err, &urlErr) { log.Printf(\"IMDS request build failed: %v\", urlErr) }\n    }\n    return fmt.Errorf(\"aws config: %w\", err)\n}","preventionTips":["Do not modify or template the hard-coded IMDS token URL","Validate any custom metadata endpoint with url.Parse before use","Keep lib/awsapi unmodified upstream to avoid malformed URL regressions"],"tags":["aws","ec2","imds","http-request","network"],"backgroundTag":"imds-request-build-failed","analyzedSha":"5079fb58f1e8e62113f90c945ad71586c797d770","analyzedAt":"2026-09-03T18:10:26.153Z","contentChangedAt":"2026-09-03T18:10:26.153Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}