kubernetes/kops · error

invalid S3 location

Error message

invalid S3 location

What it means

escapeS3Location requires the parsed URL to have exactly the scheme 's3' and a non-empty host (the bucket name). If either check fails, it returns this error because an S3 path without a bucket, or with the wrong scheme, cannot be resolved later.

Source

Thrown at pkg/model/resources/nodeup.go:289

		default:
			continue
		}
		escaped, err := escape(location)
		if err != nil {
			return "", fmt.Errorf("escaping nodeup source %q: %w", location, err)
		}
		locations[i] = escaped
	}
	return strings.Join(locations, ","), nil
}

func escapeS3Location(location string) (string, error) {
	u, err := url.Parse(location)
	if err != nil {
		return "", fmt.Errorf("parsing S3 location: %w", err)
	}
	if u.Scheme != "s3" || u.Host == "" {
		return "", fmt.Errorf("invalid S3 location")
	}

	return "s3://" + u.Host + httpbinding.EscapePath(u.Path, false), nil
}

func escapeBlobLocation(location string) (string, error) {
	u, err := url.Parse(location)
	if err != nil {
		return "", fmt.Errorf("parsing Azure Blob location: %w", err)
	}
	container, key, _ := strings.Cut(strings.TrimPrefix(u.Path, "/"), "/")
	// Reject ports, IPv6 hosts, userinfo, queries, and fragments, which the account-based
	// blob.core.windows.net URL cannot represent, so they fail here instead of in the boot retry loop.
	if u.Scheme != "azureblob" || u.Host == "" || u.Hostname() != u.Host || u.User != nil || u.RawQuery != "" || u.Fragment != "" || container == "" || key == "" {
		return "", fmt.Errorf("invalid Azure Blob location; expected azureblob://<account>/<container>/<key>")
	}

	return "azureblob://" + u.Host + httpbinding.EscapePath(u.Path, false), nil

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Ensure the location starts with exactly s3:// (lowercase) and includes a bucket: s3://bucket/key.
  2. Check for double slashes or a missing bucket after the scheme prefix.
  3. If the bucket is filled from config/flag input, validate it is non-empty before building the source string.
  4. Rebuild the nodeup script after fixing the URL.

Example fix

// before
NodeUpSource: "s3:///artifacts/nodeup"
// after
NodeUpSource: "s3://my-artifacts-bucket/artifacts/nodeup"
Defensive patterns

Strategy: validation

Validate before calling

u, _ := url.Parse(location)
if u.Scheme != "s3" || u.Host == "" {
    return errors.New("location must be s3://<bucket>/<key>")
}

Type guard

func isS3Location(loc string) bool {
    u, err := url.Parse(loc)
    return err == nil && u.Scheme == "s3" && u.Host != ""
}

Try / catch

if !isS3Location(loc) {
    return fmt.Errorf("%q must include bucket: s3://bucket/key", loc)
}

Prevention

When it happens

Trigger: A nodeup source location whose scheme is not exactly 's3' (e.g. 'S3://', 'https://', empty) or which parses with an empty host, e.g. 's3:///path/to/nodeup' or 's3://'.

Common situations: Bucket name accidentally dropped during refactoring, using an https URL where an s3:// URL is required, or a bare path like '/path/to/nodeup' passed as a source.

Related errors


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