kubernetes/kops · error
no container specified in %q; expected azureblob://<account>
Error message
no container specified in %q; expected azureblob://<account>/<container>/<key>
What it means
buildAzureBlobPath requires azureblob://<account>/<container>/<key>. After extracting the account from the host, it splits the remaining path into container and key; this error is thrown when the container segment (the first path component) is empty or missing.
Source
Thrown at util/pkg/vfs/context.go:591
u, err := url.Parse(p)
if err != nil {
return nil, fmt.Errorf("failed to parse %q: %s", p, err)
}
if u.Scheme != "azureblob" {
return nil, fmt.Errorf("invalid Azure Blob scheme: %q", p)
}
account := strings.TrimSuffix(u.Host, "/")
if account == "" {
return nil, fmt.Errorf("no storage account specified in %q; expected azureblob://<account>/<container>/<key>", p)
}
rest := strings.TrimPrefix(u.Path, "/")
container, key, _ := strings.Cut(rest, "/")
if container == "" {
return nil, fmt.Errorf("no container specified in %q; expected azureblob://<account>/<container>/<key>", p)
}
return NewAzureBlobPath(c, account, container, key), nil
}
// getAzureBlobClient returns the client for azure blob storage for the given
// storage account, caching it for future reuse.
func (c *VFSContext) getAzureBlobClient(ctx context.Context, account string) (*azblob.Client, error) {
if account == "" {
return nil, fmt.Errorf("Azure storage account is required")
}
c.mutex.Lock()
defer c.mutex.Unlock()
if client, ok := c.azureClients[account]; ok {
return client, nil
}View on GitHub (pinned to 4c8573c808)
Solutions
- Add the container name as the first path segment: azureblob://<account>/<container>/<key>.
- Ensure the key is not placed directly after the account; there must be exactly one container segment between account and key.
- Verify the container exists in the storage account (kops will not create it implicitly here).
Example fix
// before
BuildVfsPath("azureblob://myaccount/clusterstate")
// after
BuildVfsPath("azureblob://myaccount/kops-container/clusterstate") Defensive patterns
Strategy: validation
Validate before calling
u, _ := url.Parse(stateStore)
if u.Scheme == "azureblob" {
parts := strings.SplitN(strings.TrimPrefix(u.Path, "/"), "/", 2)
if len(parts) < 2 || parts[0] == "" {
return fmt.Errorf("azureblob state store %q is missing the container", stateStore)
}
} Type guard
func hasAzureBlobContainer(p string) bool {
u, err := url.Parse(p)
if err != nil || u.Scheme != "azureblob" || u.Host == "" {
return false
}
container, _, _ := strings.Cut(strings.TrimPrefix(u.Path, "/"), "/")
return container != ""
} Prevention
- Include the container as the first path segment after the account.
- Never place the object key directly after the account name.
- Document the expected URL shape where the state store is configured.
When it happens
Trigger: Calling BuildVfsPath with "azureblob://myaccount", "azureblob://myaccount/", or "azureblob://myaccount/key" (no first path segment before the key).
Common situations: State store URLs missing the container because users copy the account-only connection pattern, or keys placed directly after the account without an intermediate container name.
Related errors
- no storage account specified in %q; expected azureblob://<ac
- parsing etcd backup-store %q: %w
- parsing configStore.base %q: %w
- expected azureblob:// ConfigStore.Base for Azure cluster, go
- Azure storage account is not set on path %q
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/726f0a2aff7f50a9.
Report an issue: GitHub.