{"record":{"id":"4d2e4229675fdc13","repo":"kubernetes/kops","slug":"expected-azureblob-backup-store-got-q","errorCode":null,"errorMessage":"expected azureblob:// backup-store, got %q","messagePattern":"expected azureblob:// backup-store, got %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/model/components/etcdmanager/model.go","lineNumber":70,"sourceCode":"// etcd-manager image, returning the storage account derived from\n// configStoreBase (the single source of truth for the cluster) for\n// AZURE_STORAGE_ACCOUNT injection. Non-azureblob backup stores pass through\n// unchanged. Errors if a backup store is azureblob:// but configStoreBase is\n// not, since validation already enforces account uniformity.\n//\n// TODO: remove once etcd-manager is bumped to a release whose vendored VFS\n// understands azureblob://<account>/<container>/<key>.\nfunc resolveAzureBackupStore(configStoreBase, backupStore string) (legacyURL string, storageAccount string, err error) {\n\tif !strings.HasPrefix(backupStore, \"azureblob://\") {\n\t\treturn backupStore, \"\", nil\n\t}\n\tbp, err := vfs.Context.BuildVfsPath(backupStore)\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"parsing etcd backup-store %q: %w\", backupStore, err)\n\t}\n\tbpAzure, ok := bp.(*vfs.AzureBlobPath)\n\tif !ok {\n\t\treturn \"\", \"\", fmt.Errorf(\"expected azureblob:// backup-store, got %q\", backupStore)\n\t}\n\tcsp, err := vfs.Context.BuildVfsPath(configStoreBase)\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"parsing configStore.base %q: %w\", configStoreBase, err)\n\t}\n\tcsAzure, ok := csp.(*vfs.AzureBlobPath)\n\tif !ok {\n\t\treturn \"\", \"\", fmt.Errorf(\"backup-store %q is azureblob:// but configStore.base %q is not\", backupStore, configStoreBase)\n\t}\n\tlegacy := \"azureblob://\" + bpAzure.Container()\n\tif bpAzure.Key() != \"\" {\n\t\tlegacy += \"/\" + bpAzure.Key()\n\t}\n\treturn legacy, csAzure.Account(), nil\n}\n\n// EtcdManagerBuilder builds the manifest for the etcd-manager\ntype EtcdManagerBuilder struct {","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/model/components/etcdmanager/model.go#L52-L88","documentation":"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.","triggerScenarios":"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.","commonSituations":"AWS-style s3:// backupStore copied into an Azure cluster spec; hybrid configs migrated between clouds; tests with memfs stores passed through the Azure path.","solutions":["Set backupStore to a proper azureblob:// URL for the etcd cluster on Azure","Ensure the etcd manager config matches the cluster's cloud provider","If you need another backend, this code path (Azure legacy URL resolution) does not support it — use the generic non-Azure backupStore flow"],"exampleFix":"// before\nbackups:\n  backupStore: \"s3://my-bucket/etcd-backups\"\n// after\nbackups:\n  backupStore: \"azureblob://myaccount/etcd-backups\"","handlingStrategy":"type-guard","validationCode":"if !strings.HasPrefix(backupStore, \"azureblob://\") {\n    return fmt.Errorf(\"on Azure, etcd backupStore must start with azureblob://, got %q\", backupStore)\n}","typeGuard":"func isAzureBlobPath(p vfs.VFSPath) bool {\n    _, ok := p.(*vfs.AzureBlobPath)\n    return ok\n}","tryCatchPattern":"legacy, account, err := resolveAzureBackupStore(configStoreBase, backupStore)\nif err != nil {\n    if strings.Contains(err.Error(), \"expected azureblob:// backup-store\") {\n        // fix backupStore to azureblob:// and retry\n    }\n    return err\n}","preventionTips":["Keep backupStore backend consistent with the cloud provider","Reject s3:// backupStores in Azure cluster templates","Verify specs after migrating clusters between clouds"],"tags":["azure","etcd","type-mismatch","config"],"backgroundTag":"unsupported-storage-backend","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}