kubernetes/kops · error

expected azureblob:// backup-store, got %q

Error message

expected azureblob:// backup-store, got %q

What it means

This error fires when a backupStore string reaches resolveAzureBackupStore with a prefix other than azureblob:// is impossible — actually it fires when BuildVfsPath succeeded but the parsed path is not a vfs.AzureBlobPath, meaning the store URL resolved to another backend type. The function only supports Azure blob storage for this conversion.

Source

Thrown at pkg/model/components/etcdmanager/model.go:70

// etcd-manager image, returning the storage account derived from
// configStoreBase (the single source of truth for the cluster) for
// AZURE_STORAGE_ACCOUNT injection. Non-azureblob backup stores pass through
// unchanged. Errors if a backup store is azureblob:// but configStoreBase is
// not, since validation already enforces account uniformity.
//
// TODO: remove once etcd-manager is bumped to a release whose vendored VFS
// understands azureblob://<account>/<container>/<key>.
func resolveAzureBackupStore(configStoreBase, backupStore string) (legacyURL string, storageAccount string, err error) {
	if !strings.HasPrefix(backupStore, "azureblob://") {
		return backupStore, "", nil
	}
	bp, err := vfs.Context.BuildVfsPath(backupStore)
	if err != nil {
		return "", "", fmt.Errorf("parsing etcd backup-store %q: %w", backupStore, err)
	}
	bpAzure, ok := bp.(*vfs.AzureBlobPath)
	if !ok {
		return "", "", fmt.Errorf("expected azureblob:// backup-store, got %q", backupStore)
	}
	csp, err := vfs.Context.BuildVfsPath(configStoreBase)
	if err != nil {
		return "", "", fmt.Errorf("parsing configStore.base %q: %w", configStoreBase, err)
	}
	csAzure, ok := csp.(*vfs.AzureBlobPath)
	if !ok {
		return "", "", fmt.Errorf("backup-store %q is azureblob:// but configStore.base %q is not", backupStore, configStoreBase)
	}
	legacy := "azureblob://" + bpAzure.Container()
	if bpAzure.Key() != "" {
		legacy += "/" + bpAzure.Key()
	}
	return legacy, csAzure.Account(), nil
}

// EtcdManagerBuilder builds the manifest for the etcd-manager
type EtcdManagerBuilder struct {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Set backupStore to a proper azureblob:// URL for the etcd cluster on Azure
  2. Ensure the etcd manager config matches the cluster's cloud provider
  3. If you need another backend, this code path (Azure legacy URL resolution) does not support it — use the generic non-Azure backupStore flow

Example fix

// before
backups:
  backupStore: "s3://my-bucket/etcd-backups"
// after
backups:
  backupStore: "azureblob://myaccount/etcd-backups"
Defensive patterns

Strategy: type-guard

Validate before calling

if !strings.HasPrefix(backupStore, "azureblob://") {
    return fmt.Errorf("on Azure, etcd backupStore must start with azureblob://, got %q", backupStore)
}

Type guard

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

Try / catch

legacy, account, err := resolveAzureBackupStore(configStoreBase, backupStore)
if err != nil {
    if strings.Contains(err.Error(), "expected azureblob:// backup-store") {
        // fix backupStore to azureblob:// and retry
    }
    return err
}

Prevention

When it happens

Trigger: Calling buildPod on Azure where the etcd backupStore parses to a non-Azure VFS path type (e.g. s3://, file://) — typically a misconfigured cluster where backupStore does not match the cloud.

Common situations: AWS-style s3:// backupStore copied into an Azure cluster spec; hybrid configs migrated between clouds; tests with memfs stores passed through the Azure path.

Related errors


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