kubernetes/kops · error

%s is not a valid S3 URL

Error message

%s is not a valid S3 URL

What it means

VFSPath validates an S3 URL against s3UrlRegexp and converts it to canonical s3://bucket/path form. This error is thrown when the input string doesn't match the S3 URL pattern at all — wrong scheme, missing scheme, an S3 path that isn't parseable, or an entirely non-S3 URL passed where a state-store S3 URL is expected.

Source

Thrown at util/pkg/vfs/s3context.go:364

	config, err := awsconfig.LoadDefaultConfig(ctx, awsconfig.WithHTTPClient(shortTimeout))
	if err != nil {
		return "", fmt.Errorf("failed to load AWS config: %w", err)
	}

	client := imds.NewFromConfig(config)

	metadataRegion, err := client.GetRegion(ctx, &imds.GetRegionInput{})
	if err != nil {
		return "", fmt.Errorf("getting AWS region from metadata: %w", err)
	}

	return metadataRegion.Region, nil
}

func VFSPath(url string) (string, error) {
	if !s3UrlRegexp.MatchString(url) {
		return "", fmt.Errorf("%s is not a valid S3 URL", url)
	}
	groupNames := s3UrlRegexp.SubexpNames()
	result := s3UrlRegexp.FindAllStringSubmatch(url, -1)[0]

	captured := map[string]string{}
	for i, value := range result {
		if value != "" {
			captured[groupNames[i]] = value
		}
	}
	bucket := captured["bucket"]
	path := captured["path"]
	if bucket == "" {
		if path == "" {
			return "", fmt.Errorf("%s is not a valid S3 URL. No bucket defined.", url)
		}
		return fmt.Sprintf("s3:/%s", path), nil
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Use canonical form: kops create cluster --state s3://<bucket>[/<prefix>], e.g. s3://my-kops-state or s3://my-kops-state/clusters
  2. Check for scheme typos — must start with s3:// (double slash); remove http(s):// prefixes and stray quotes/whitespace
  3. If the value comes from $KOPS_STATE_STORE, echo it and re-export without trailing slashes or quotes
  4. For non-S3 stores, use the correct scheme for that backend (gs:// for GCS, azureblob:// etc.) — VFSPath only accepts S3
  5. Validate locally by matching against the regex expected by kops before scripting: the URL must have scheme s3:// and a non-empty bucket

Example fix

// before
export KOPS_STATE_STORE=my-kops-state
kops create cluster ...
// error: my-kops-state is not a valid S3 URL
// after
export KOPS_STATE_STORE=s3://my-kops-state
Defensive patterns

Strategy: validation

Validate before calling

// Validate the state-store URL shape before invoking kops
[[ "$KOPS_STATE_STORE" =~ ^s3://[a-z0-9][a-z0-9.-]{2,62} ]] \
  || { echo "KOPS_STATE_STORE must be s3://<bucket>[/<prefix>], got: $KOPS_STATE_STORE"; exit 1; }

Type guard

func isValidS3URL(url string) bool {
	return strings.HasPrefix(url, "s3://") && len(url) > len("s3://")
}

Prevention

When it happens

Trigger: s3UrlRegexp.MatchString(url) returns false in VFSPath. Callers pass malformed URLs such as 'mybucket/keys' (no s3:// prefix), 'http://bucket/path', 's3:/bucket' (single slash without path group match), trailing/invalid characters, or a bare hostname. Reached via buildVFSPath when constructing a cluster state store path.

Common situations: Users setting --state to a bucket name without the s3:// scheme (kops create cluster --state mybucket); copying an https console URL of a bucket instead of its S3 URI; quoting/whitespace artifacts from shell variables; typos like s3//bucket or missing slashes.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/b112664a9f517744. Report an issue: GitHub.