kubernetes/kops · error

expected azureblob:// URL, got %q

Error message

expected azureblob:// URL, got %q

What it means

azureBlobAccount builds a vfs path from a raw azureblob:// URL and asserts the result is an *vfs.AzureBlobPath. If vfs.Context.BuildVfsPath returns a different path type (or the URL is not a valid azureblob URL), the function cannot extract a storage account name and returns this error. It is used by validateAzureBlobAccountUniformity to compare storage accounts across the cluster spec.

Source

Thrown at pkg/apis/kops/validation/validation.go:1660

	}

	return allErrs
}

// azureBlobAccount returns the storage account encoded in an azureblob:// URL,
// or "" with no error if the URL is not azureblob://. Returns an error only if
// the URL has the azureblob:// prefix but fails to parse.
func azureBlobAccount(rawURL string) (string, error) {
	if !strings.HasPrefix(rawURL, "azureblob://") {
		return "", nil
	}
	p, err := vfs.Context.BuildVfsPath(rawURL)
	if err != nil {
		return "", err
	}
	azPath, ok := p.(*vfs.AzureBlobPath)
	if !ok {
		return "", fmt.Errorf("expected azureblob:// URL, got %q", rawURL)
	}
	return azPath.Account(), nil
}

// validateAzureBlobAccountUniformity enforces that every azureblob:// URL in
// the cluster spec uses the same storage account as configStore.base. Any
// azureblob:// URL elsewhere in the spec is rejected when configStore.base is
// not itself azureblob://.
func validateAzureBlobAccountUniformity(spec *kops.ClusterSpec, fieldPath *field.Path) field.ErrorList {
	var allErrs field.ErrorList
	csPath := fieldPath.Child("configStore")

	canonical := ""
	if strings.HasPrefix(spec.ConfigStore.Base, "azureblob://") {
		account, err := azureBlobAccount(spec.ConfigStore.Base)
		if err != nil {
			allErrs = append(allErrs, field.Invalid(csPath.Child("base"), spec.ConfigStore.Base, err.Error()))
			return allErrs

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Use a well-formed URL of the form azureblob://<account>/<container>/<path> for all cluster storage locations.
  2. Verify the scheme is exactly `azureblob://` (two slashes) and that vfs can parse it (test with `kops get cluster` or a small vfs.Context.BuildVfsPath call).
  3. If uniformity validation fails, ensure every azureblob:// URL in the spec uses the same storage account as configStore.base.

Example fix

// before
configBase: s3://my-bucket/cluster.example.com
// after
configBase: azureblob://mystorageaccount/kops/cluster.example.com
Defensive patterns

Strategy: type-guard

Validate before calling

u, err := url.Parse(rawURL)
if err != nil || u.Scheme != "azureblob" {
    return fmt.Errorf("not an azureblob URL: %q", rawURL)
}

Type guard

func isAzureBlobPath(p vfs.Path) (*vfs.AzureBlobPath, bool) {
    az, ok := p.(*vfs.AzureBlobPath)
    return az, ok
}

Prevention

When it happens

Trigger: Passing a non-azureblob URL (e.g. s3://, file://, or a malformed azureblob:// string) into azureBlobAccount; BuildVfsPath parses it into a different vfs.Path concrete type so the type assertion fails.

Common situations: Configuring configBase or a mirror with the wrong scheme when migrating a cluster to Azure; copy-pasting an S3 or Azure Files (file://) URL; a typo like azureblob:/account (single slash) that parses as something else.

Related errors


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