{"record":{"id":"126d91fd4e7d31fc","repo":"grafana/k6","slug":"sigv4-config-region-awsaccesskeyid-awssecre","errorCode":null,"errorMessage":"sigV4 config `Region`, `AwsAccessKeyID`, `AwsSecretAccessKey` must all be set","messagePattern":"sigV4 config `Region`, `AwsAccessKeyID`, `AwsSecretAccessKey` must all be set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/output/prometheusrw/sigv4/tripper.go","lineNumber":31,"sourceCode":"\tnext   http.RoundTripper\n}\n\n// Config holds aws access configurations\ntype Config struct {\n\tRegion             string\n\tAwsAccessKeyID     string\n\tAwsSecretAccessKey string\n}\n\nfunc (c *Config) validate() error {\n\tif c == nil {\n\t\treturn errors.New(\"config should not be nil\")\n\t}\n\thasRegion := len(strings.TrimSpace(c.Region)) != 0\n\thasAccessID := len(strings.TrimSpace(c.AwsAccessKeyID)) != 0\n\thasSecretAccessKey := len(strings.TrimSpace(c.AwsSecretAccessKey)) != 0\n\tif !hasRegion || !hasAccessID || !hasSecretAccessKey {\n\t\treturn errors.New(\"sigV4 config `Region`, `AwsAccessKeyID`, `AwsSecretAccessKey` must all be set\")\n\t}\n\treturn nil\n}\n\n// NewRoundTripper creates a new sigv4 round tripper\nfunc NewRoundTripper(config *Config, next http.RoundTripper) (*Tripper, error) {\n\tif err := config.validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif next == nil {\n\t\tnext = http.DefaultTransport\n\t}\n\n\ttripper := &Tripper{\n\t\tconfig: config,\n\t\tnext:   next,\n\t\tsigner: newDefaultSigner(config),","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/output/prometheusrw/sigv4/tripper.go#L13-L49","documentation":"Returned by sigv4.Config.validate() (via NewRoundTripper) when Region, AwsAccessKeyID, or AwsSecretAccessKey is empty after trimming whitespace. This is the second, lower-level guard behind the output-level partial-config check (config.go:141) and also fires for programmatic users of the exported sigv4 package, including a nil config.","triggerScenarios":"Calling sigv4.NewRoundTripper(&sigv4.Config{Region: \"us-east-1\"}, transport) from Go code; constructing the Config with fields that contain only whitespace; passing a nil *Config (yields the sibling 'config should not be nil' error); embedding k6 and wiring the sigv4 tripper manually.","commonSituations":"Go integrations building the SigV4 round tripper themselves; tests that instantiate partial configs; code that reads the three values from different sources (env, file, IMDS) where one read fails and leaves an empty string instead of erroring.","solutions":["Populate all three fields with non-blank strings before calling NewRoundTripper","Pre-trim and check each value at the point where you build the Config; fail with a clear message naming the missing field","If you have no AWS credentials, do not wrap the transport with sigv4 at all"],"exampleFix":"// before\nrt, err := sigv4.NewRoundTripper(&sigv4.Config{Region: \"us-east-1\"}, http.DefaultTransport)\n// err: sigV4 config `Region`, `AwsAccessKeyID`, `AwsSecretAccessKey` must all be set\n\n// after\ncfg := &sigv4.Config{\n\tRegion:          \"us-east-1\",\n\tAwsAccessKeyID:  os.Getenv(\"AWS_ACCESS_KEY_ID\"),\n\tAwsSecretAccessKey: os.Getenv(\"AWS_SECRET_ACCESS_KEY\"),\n}\nif strings.TrimSpace(cfg.AwsAccessKeyID) == \"\" || strings.TrimSpace(cfg.AwsSecretAccessKey) == \"\" {\n\treturn errors.New(\"AWS credentials missing; refusing to build sigv4 transport\")\n}\nrt, err := sigv4.NewRoundTripper(cfg, http.DefaultTransport)","handlingStrategy":"validation","validationCode":"// Go: guard before building the round tripper.\nfunc validSigV4(c *sigv4.Config) bool {\n\tif c == nil { return false }\n\ttrim := func(s string) string { return strings.TrimSpace(s) }\n\treturn trim(c.Region) != \"\" && trim(c.AwsAccessKeyID) != \"\" && trim(c.AwsSecretAccessKey) != \"\"\n}\nif !validSigV4(cfg) { return errors.New(\"refusing sigv4: region/access key/secret key incomplete\") }","typeGuard":"func isSigV4ConfigComplete(c *sigv4.Config) bool {\n\tif c == nil {\n\t\treturn false\n\t}\n\treturn strings.TrimSpace(c.Region) != \"\" &&\n\t\tstrings.TrimSpace(c.AwsAccessKeyID) != \"\" &&\n\t\tstrings.TrimSpace(c.AwsSecretAccessKey) != \"\"\n}","tryCatchPattern":"In Go, wrap sigv4.NewRoundTripper in a check of the returned error and fail configuration-time, not request-time; do not fall back to an unsigned transport on failure.","preventionTips":["Trim and assert all three fields non-empty where the Config is built, not where it is used","Load AWS credentials from one source (env, file, or IMDS) so partial reads are impossible","Unit-test the config builder with each field missing to confirm it refuses early"],"tags":["k6","prometheus","sigv4","aws","go","validation"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}