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

  1. Add the container name as the first path segment: azureblob://<account>/<container>/<key>.
  2. Ensure the key is not placed directly after the account; there must be exactly one container segment between account and key.
  3. 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

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


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