kubernetes/kops · error
invalid s3 path: %q
Error message
invalid s3 path: %q
What it means
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.
Source
Thrown at util/pkg/vfs/context.go:349
}
noMoreRetries := i >= backoff.Steps
if !noMoreRetries && err != nil {
klog.V(2).Infof("retrying after error %v", err)
}
if noMoreRetries {
klog.V(2).Infof("hit maximum retries %d with error %v", i, err)
return done, err
}
}
}
func (c *VFSContext) buildS3Path(p string) (*S3Path, error) {
endpoint := os.Getenv("S3_ENDPOINT")
u, err := url.Parse(p)
if err != nil {
return nil, fmt.Errorf("invalid s3 path: %q", p)
}
if u.Scheme != "s3" {
return nil, fmt.Errorf("invalid s3 path: %q", p)
}
bucket := strings.TrimSuffix(u.Host, "/")
if bucket == "" {
return nil, fmt.Errorf("invalid s3 path: %q", p)
}
s3path := newS3Path(c.s3Context, u.Scheme, bucket, u.Path, true, func(o *s3.Options) {
if endpoint != "" {
o.BaseEndpoint = aws.String(endpoint)
o.UsePathStyle = true
o.DisableLogOutputChecksumValidationSkipped = true
} else {
o.EndpointResolverV2 = &ResolverV2{}
}View on GitHub (pinned to 4c8573c808)
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.
Example fix
// before
statePath := fmt.Sprintf("s3://%s/state", rawBucketName) // rawBucketName contains "%zz" or a newline
// after
statePath := "s3://" + url.PathEscape(rawBucketName) + "/state" Defensive patterns
Strategy: validation
Validate before calling
func validS3StorePath(p string) bool {
u, err := url.Parse(p)
return err == nil && u.Scheme == "s3" && strings.TrimSuffix(u.Host, "/") != ""
}
if !validS3StorePath(os.Getenv("KOPS_STATE_STORE")) {
return fmt.Errorf("KOPS_STATE_STORE must be a valid s3://bucket/path URL, got %q", os.Getenv("KOPS_STATE_STORE"))
} Type guard
func isParsableURL(p string) bool {
_, err := url.Parse(p)
return err == nil
} Try / catch
p, err := vfs.Context.BuildVfsPath(raw)
if err != nil {
if strings.Contains(err.Error(), "invalid s3 path") {
return fmt.Errorf("malformed S3 state store %q: %w", raw, err)
}
return err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- cannot parse VFS path %q: %v
- error loading NodeupConfig %q: %v
- ReadOnlyError
- error reading addons from %q: %v
- unexpected kind for cluster, got %T, want kops.Cluster
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/06082eaef5a27725.
Report an issue: GitHub.