{"record":{"id":"6dac5bc691752b72","repo":"kubernetes/kops","slug":"invalid-spaces-path-q","errorCode":null,"errorMessage":"invalid spaces path: %q","messagePattern":"invalid spaces path: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/pkg/vfs/context.go","lineNumber":380,"sourceCode":"\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}\n\t})\n\treturn s3path, nil\n}\n\nfunc (c *VFSContext) buildDOPath(p string) (*S3Path, error) {\n\tendpoint := os.Getenv(\"S3_ENDPOINT\")\n\tif endpoint == \"\" {\n\t\treturn nil, fmt.Errorf(\"required S3_ENDPOINT env var for path: %q\", p)\n\t}\n\n\tu, err := url.Parse(p)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid spaces path: %q\", p)\n\t}\n\tif u.Scheme != \"do\" {\n\t\treturn nil, fmt.Errorf(\"invalid spaces path: %q\", p)\n\t}\n\n\tbucket := strings.TrimSuffix(u.Host, \"/\")\n\tif bucket == \"\" {\n\t\treturn nil, fmt.Errorf(\"invalid spaces path: %q\", p)\n\t}\n\n\ts3path := newS3Path(c.s3Context, u.Scheme, bucket, u.Path, false, func(o *s3.Options) {\n\t\to.BaseEndpoint = aws.String(endpoint)\n\t\to.UsePathStyle = true\n\t\to.DisableLogOutputChecksumValidationSkipped = true\n\t})\n\treturn s3path, nil\n}\n","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/util/pkg/vfs/context.go#L362-L398","documentation":"buildDOPath failed to parse the given path as a URL. DigitalOcean Spaces locations must be parseable do://bucket/key URLs; when url.Parse returns an error, the path is rejected with this message.","triggerScenarios":"Calling BuildVfsPath with a do:// string that url.Parse rejects — invalid percent-escapes (do://bucket/%zz), control characters, or unescaped non-ASCII characters in bucket/key.","commonSituations":"Spaces store path built by templating/shell interpolation that injects malformed characters; copy-paste introducing stray bytes into KOPS_STATE_STORE.","solutions":["Inspect the quoted path in the error; remove or percent-encode invalid characters.","Use url.PathEscape for dynamic bucket/key segments when composing the path.","Set KOPS_STATE_STORE to a clean literal like do://my-space/clusters."],"exampleFix":"// before\nstatePath := fmt.Sprintf(\"do://%s/state\", nameWithControlChars)\n// after\nstatePath := \"do://\" + url.PathEscape(name) + \"/state\"","handlingStrategy":"validation","validationCode":"func validDOStorePath(p string) bool {\n\tu, err := url.Parse(p)\n\treturn err == nil && u.Scheme == \"do\" && strings.TrimSuffix(u.Host, \"/\") != \"\"\n}\nif !validDOStorePath(os.Getenv(\"KOPS_STATE_STORE\")) {\n\treturn fmt.Errorf(\"KOPS_STATE_STORE must be a valid do://space/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 spaces path\") {\n\t\treturn fmt.Errorf(\"malformed Spaces path %q: %w\", raw, err)\n\t}\n\treturn err\n}","preventionTips":["Set KOPS_STATE_STORE as a literal do://space/path value.","Percent-encode dynamic segments with url.PathEscape.","Avoid interpolating raw/untrusted strings into the store path.","Echo the path with %q to spot hidden control characters."],"tags":["digitalocean","spaces","url-parsing","vfs"],"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-12T07:17:12.445Z"}