kubernetes/kops · error
parsing etcd backup-store %q: %w
Error message
parsing etcd backup-store %q: %w
What it means
resolveAzureBackupStore handles etcd backup stores on Azure by parsing the azureblob:// backup-store URL into a vfs.AzureBlobPath to derive the legacy URL. If vfs.Context.BuildVfsPath fails to parse the backupStore string, the error is wrapped as 'parsing etcd backup-store'.
Source
Thrown at pkg/model/components/etcdmanager/model.go:66
)
// resolveAzureBackupStore rewrites azureblob://<account>/<container>/<key> into
// the legacy azureblob://<container>/<key> shape understood by the pinned
// 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(), nilView on GitHub (pinned to 4c8573c808)
Solutions
- Fix the azureblob:// backupStore URL (azureblob://<account>/<container>[/<key>]) in the etcd cluster spec
- Check the wrapped inner error for the exact parse failure
- Validate the storage account/container names against Azure naming rules
Example fix
// before backups: backupStore: "azureblob:///bad url" // after backups: backupStore: "azureblob://myaccount/etcd-backups/main"
Defensive patterns
Strategy: validation
Validate before calling
if strings.HasPrefix(backupStore, "azureblob://") {
rest := strings.TrimPrefix(backupStore, "azureblob://")
if rest == "" || strings.ContainsAny(rest, " ?#") {
return fmt.Errorf("malformed azureblob backupStore: %q", backupStore)
}
} Type guard
null
Try / catch
legacy, account, err := resolveAzureBackupStore(configStoreBase, backupStore)
if err != nil {
if strings.Contains(err.Error(), "parsing etcd backup-store") {
// correct the backupStore URI and retry
}
return err
} Prevention
- Validate etcd backupStore URLs in cluster specs before apply
- Follow the azureblob://<account>/<container>[/<key>] format
- Check wrapped inner errors for root cause
When it happens
Trigger: An etcd cluster spec on Azure with a backupStore starting with azureblob:// that is malformed (bad container/key syntax) so BuildVfsPath returns an error during buildPod.
Common situations: Hand-edited etcdClusters backups config; mistyped container name; unsupported characters in the blob path; config generated by an older kOps version with an incompatible URL form.
Related errors
- parsing configStore.base %q: %w
- failed to parse %q: %s
- no storage account specified in %q; expected azureblob://<ac
- no container specified in %q; expected azureblob://<account>
- error parsing path for etcd manifest %s: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/5bd0842048b61ccf.
Report an issue: GitHub.