kubernetes/kops · error
parsing StorageAccountID: %w
Error message
parsing StorageAccountID: %w
What it means
kops wraps arm.ParseResourceID failures while building the Terraform target for Azure clusters. The cluster spec's spec.cloudProvider.azure.storageAccountID must be a fully-qualified Azure Resource Manager resource ID (e.g. /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<name>); anything else (account name, URL, typo) fails to parse and the apply aborts with this wrapped error.
Source
Thrown at upup/pkg/fi/cloudup/apply_cluster.go:783
target = linode.NewAPITarget(cloud.(linode.LinodeCloud))
case kops.CloudProviderMetal:
target = metal.NewAPITarget(cloud.(*metal.Cloud), nil)
default:
return nil, fmt.Errorf("direct configuration not supported with CloudProvider:%q", cluster.GetCloudProvider())
}
case TargetTerraform:
outDir := c.OutDir
tf := terraform.NewTerraformTarget(cloud, project, outDir, cluster.Spec.Target)
// Register an azurerm provider alias for state storage blobs.
// If the storage account is in a different subscription, pass subscription_id.
if azureSpec := cluster.Spec.CloudProvider.Azure; azureSpec != nil {
args := map[string]string{}
if azureSpec.StorageAccountID != "" {
storageAccountID, err := arm.ParseResourceID(azureSpec.StorageAccountID)
if err != nil {
return nil, fmt.Errorf("parsing StorageAccountID: %w", err)
}
if storageAccountID.SubscriptionID != azureSpec.SubscriptionID {
args["subscription_id"] = storageAccountID.SubscriptionID
}
}
tf.AzureStorageAccountID = azureSpec.StorageAccountID
tf.EnsureTerraformProvider("azurerm", args)
}
// We include a few "util" variables in the TF output
if err := tf.AddOutputVariable("region", terraformWriter.LiteralFromStringValue(cloud.Region())); err != nil {
return nil, err
}
if project != "" {
if err := tf.AddOutputVariable("project", terraformWriter.LiteralFromStringValue(project)); err != nil {
return nil, err
}View on GitHub (pinned to 4c8573c808)
Solutions
- Set spec.cloudProvider.azure.storageAccountID to the full ARM resource ID, e.g. /subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<account>
- Get the correct ID with: az storage account show -n <account> -g <rg> --query id -o tsv
- Clear the field entirely if the default (same-subscription) storage account behavior is intended — the check only runs when the value is non-empty
- Re-run kops update cluster --target=terraform to confirm parsing succeeds
Example fix
// before (cluster.yaml)
spec:
cloudProvider:
azure:
storageAccountID: mystorageaccount1
// after
spec:
cloudProvider:
azure:
storageAccountID: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/kops-rg/providers/Microsoft.Storage/storageAccounts/mystorageaccount1 Defensive patterns
Strategy: validation
Validate before calling
func validAzureStorageAccountID(id string) bool {
re := regexp.MustCompile(`^/subscriptions/[0-9a-fA-F-]{36}/resourceGroups/[^/]+/providers/Microsoft\.Storage/storageAccounts/[^/]+$`)
return id == "" || re.MatchString(id)
}
// check before apply:
if !validAzureStorageAccountID(cluster.Spec.CloudProvider.Azure.StorageAccountID) {
return fmt.Errorf("storageAccountID must be a full ARM resource ID")
} Type guard
func isARMResourceID(s string) bool {
return strings.HasPrefix(s, "/subscriptions/") && strings.Contains(s, "/providers/")
} Prevention
- Always copy the resource ID (not the name) from az storage account show --query id
- Store the full ARM ID in the cluster spec, never a bare account name
- Validate the spec with kops toolbox template or a linter before apply
- Leave the field empty if you don't need a cross-subscription storage account
When it happens
Trigger: Running kops with --target=terraform on an Azure cluster whose spec.cloudProvider.azure.storageAccountID is set to a value arm.ParseResourceID cannot parse — e.g. a bare storage account name, a blob endpoint URL, a wrong-cased or truncated resource ID path.
Common situations: Users paste the storage account name instead of its resource ID; copying the ID from the Azure portal with the 'subscriptions' segment misspelled; hand-editing the cluster spec and omitting the /subscriptions/<id>/ prefix; using an az CLI output field like primaryEndpoints blob URL.
Related errors
- cloud provider Azure requires the AzureTerraform feature fla
- storage profile is required for VMScaleSet %q
- os disk is required for VMScaleSet %q
- spotinst: found multiple role tags %q vs %q
- reading data: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/1cf01b997f1b85ba.
Report an issue: GitHub.