{"record":{"id":"2d99fef86c730987","repo":"kubernetes/kops","slug":"invalid-hetzner-object-storage-path-q","errorCode":null,"errorMessage":"invalid Hetzner Object Storage path: %q","messagePattern":"invalid Hetzner Object Storage path: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/pkg/vfs/context.go","lineNumber":437,"sourceCode":"\t\to.BaseEndpoint = aws.String(endpoint)\n\t\to.UsePathStyle = true\n\t\to.DisableLogOutputChecksumValidationSkipped = true\n\t\t// Akamai (Linode) requires checksum-when-required behavior\n\t\to.RequestChecksumCalculation = aws.RequestChecksumCalculationWhenRequired\n\t\to.ResponseChecksumValidation = aws.ResponseChecksumValidationWhenRequired\n\t})\n\treturn s3path, nil\n}\n\nfunc (c *VFSContext) buildHetznerPath(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 Hetzner Object Storage path: %q\", p)\n\t}\n\tif u.Scheme != \"hos\" {\n\t\treturn nil, fmt.Errorf(\"invalid Hetzner object storage path: %q\", p)\n\t}\n\n\tbucket := strings.TrimSuffix(u.Host, \"/\")\n\tif bucket == \"\" {\n\t\treturn nil, fmt.Errorf(\"invalid Hetzner object storage 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":419,"sourceCodeEnd":455,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/util/pkg/vfs/context.go#L419-L455","documentation":"When parsing a Hetzner Object Storage VFS path, buildHetznerPath expects a URL it can parse and whose scheme is \"hos\". If url.Parse itself fails on the raw string, kOps throws this variant (with capital-O \"Object Storage\") to signal the path is not a parseable URL at all, before any scheme check happens.","triggerScenarios":"BuildVfsPath dispatches to buildHetznerPath (after S3_ENDPOINT is set) and url.Parse(p) returns a non-nil error for the given path string.","commonSituations":"State-store strings containing characters url.Parse rejects or misinterprets (unescaped spaces, control characters, stray colons like hos://:bucket); a mangled flag value pasted from docs or a script; a shell variable expansion that produced an empty or corrupted URL.","solutions":["Print the exact state store value being passed and re-check for stray characters or whitespace","Rewrite the path in the canonical form hos://<bucket>/<key>","Quote the flag in the shell so shell metacharacters don't corrupt it: --state-store=\"hos://my-bucket\"","Check any script/env interpolation that builds the state store string for accidental truncation"],"exampleFix":"// before (unparseable)\n--state-store=hos://my bucket\n// after\n--state-store=\"hos://my-bucket\"","handlingStrategy":"validation","validationCode":"if _, err := url.Parse(stateStore); err != nil {\n\treturn fmt.Errorf(\"state store %q is not a valid URL: %w\", stateStore, err)\n}","typeGuard":null,"tryCatchPattern":"p, err := vfs.Context.BuildVfsPath(stateStore)\nif err != nil {\n\tif strings.Contains(err.Error(), \"invalid Hetzner Object Storage path\") {\n\t\treturn fmt.Errorf(\"state store %q failed URL parsing; use hos://<bucket>\", stateStore)\n\t}\n\treturn err\n}","preventionTips":["Quote --state-store values in the shell to prevent metacharacter corruption","Keep state store strings to the form hos://<bucket>/<key>","Avoid unescaped spaces and control characters in configured URLs"],"tags":["vfs","hetzner","url-parsing"],"backgroundTag":"invalid-vfs-path","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"}