{"record":{"id":"06082eaef5a27725","repo":"kubernetes/kops","slug":"invalid-s3-path-q","errorCode":null,"errorMessage":"invalid s3 path: %q","messagePattern":"invalid s3 path: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/pkg/vfs/context.go","lineNumber":349,"sourceCode":"\t\t}\n\t\tnoMoreRetries := i >= backoff.Steps\n\t\tif !noMoreRetries && err != nil {\n\t\t\tklog.V(2).Infof(\"retrying after error %v\", err)\n\t\t}\n\n\t\tif noMoreRetries {\n\t\t\tklog.V(2).Infof(\"hit maximum retries %d with error %v\", i, err)\n\t\t\treturn done, err\n\t\t}\n\t}\n}\n\nfunc (c *VFSContext) buildS3Path(p string) (*S3Path, error) {\n\tendpoint := os.Getenv(\"S3_ENDPOINT\")\n\n\tu, err := url.Parse(p)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid s3 path: %q\", p)\n\t}\n\tif u.Scheme != \"s3\" {\n\t\treturn nil, fmt.Errorf(\"invalid s3 path: %q\", p)\n\t}\n\n\tbucket := strings.TrimSuffix(u.Host, \"/\")\n\tif bucket == \"\" {\n\t\treturn nil, fmt.Errorf(\"invalid s3 path: %q\", p)\n\t}\n\n\ts3path := newS3Path(c.s3Context, u.Scheme, bucket, u.Path, true, func(o *s3.Options) {\n\t\tif endpoint != \"\" {\n\t\t\to.BaseEndpoint = aws.String(endpoint)\n\t\t\to.UsePathStyle = true\n\t\t\to.DisableLogOutputChecksumValidationSkipped = true\n\t\t} else {\n\t\t\to.EndpointResolverV2 = &ResolverV2{}\n\t\t}","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/util/pkg/vfs/context.go#L331-L367","documentation":"VFSContext.buildS3Path failed to parse the given path as a URL. The vfs layer requires S3 locations to be parseable URLs with the s3:// scheme; when url.Parse errors, it returns this error wrapping the original path.","triggerScenarios":"Calling BuildVfsPath with a string that url.Parse rejects (e.g. containing control characters, invalid percent-escapes like 's3://bucket/%zz', or unescaped non-ASCII data) so parsing fails before the scheme check.","commonSituations":"Cluster config or KOPS_STATE_STORE values constructed programmatically (shell interpolation, templating) that inject raw bytes, newlines, or malformed percent-encoding into the store path.","solutions":["Print and inspect the exact path in the error message (%q shows escapes); fix the malformed characters or percent-encoding.","URL-escape dynamic components before composing the path, e.g. url.PathEscape for bucket/key segments.","Ensure KOPS_STATE_STORE is set to a plain s3://bucket/path value without control characters or stray quotes.","Set KOPS_STATE_STORE explicitly if it is empty or contains whitespace from the environment."],"exampleFix":"// before\nstatePath := fmt.Sprintf(\"s3://%s/state\", rawBucketName) // rawBucketName contains \"%zz\" or a newline\n// after\nstatePath := \"s3://\" + url.PathEscape(rawBucketName) + \"/state\"","handlingStrategy":"validation","validationCode":"func validS3StorePath(p string) bool {\n\tu, err := url.Parse(p)\n\treturn err == nil && u.Scheme == \"s3\" && strings.TrimSuffix(u.Host, \"/\") != \"\"\n}\nif !validS3StorePath(os.Getenv(\"KOPS_STATE_STORE\")) {\n\treturn fmt.Errorf(\"KOPS_STATE_STORE must be a valid s3://bucket/path URL, got %q\", os.Getenv(\"KOPS_STATE_STORE\"))\n}","typeGuard":"func isParsableURL(p string) bool {\n\t_, err := url.Parse(p)\n\treturn err == nil\n}","tryCatchPattern":"p, err := vfs.Context.BuildVfsPath(raw)\nif err != nil {\n\tif strings.Contains(err.Error(), \"invalid s3 path\") {\n\t\treturn fmt.Errorf(\"malformed S3 state store %q: %w\", raw, err)\n\t}\n\treturn err\n}","preventionTips":["Always set KOPS_STATE_STORE as a literal s3://bucket/path value.","Percent-encode dynamic segments with url.PathEscape before composing paths.","Avoid interpolating untrusted/raw strings into the store path.","Echo the path with %q formatting to spot hidden control characters."],"tags":["s3","url-parsing","vfs","go"],"backgroundTag":"invalid-url-format","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}