hashicorp/terraform · error
new blob client
Error message
new blob client: %v
What it means
Thrown by getBlobClient when blobs.NewWithBaseUri(baseUri) fails. The baseUri comes from either accountDetail.DataPlaneEndpoint(EndpointTypeBlob) or naiveStorageAccountBlobBaseURL(environment, accountName). The giovanni SDK validates the URL; this fires when baseUri is not a parseable absolute URL (missing scheme/host, illegal characters).
Solutions
- Verify storage_account_name is all-lowercase, 3-24 chars, alphanumerics only.
- If using a custom environment, check metadata_host returns the correct blob endpoint via TF_LOG=DEBUG.
- Toggle lookup_blob_endpoint: if naive URL is wrong, set it true to learn from ARM; if ARM returns wrong URL, set it false to use the environment-derived naive URL.
- Re-run with TF_LOG=DEBUG to print the actual baseUri being passed to NewWithBaseUri.
Example fix
// before
terraform {
backend "azurerm" {
storage_account_name = "MyAccount"
}
}
// after
terraform {
backend "azurerm" {
storage_account_name = "myaccount"
}
} Defensive patterns
Strategy: validation
Validate before calling
// Validate the blob base URL is parseable before constructing the giovanni client.
func validateBlobBaseURL(env environments.Environment, accountName string) error {
base, err := naiveStorageAccountBlobBaseURL(env, accountName)
if err != nil { return err }
u, err := url.Parse(base)
if err != nil { return fmt.Errorf("invalid blob base url %q: %w", base, err) }
if u.Scheme != "https" || u.Host == "" { return fmt.Errorf("blob base url must be https with a host: %q", base) }
return nil
} Prevention
- Lowercase and validate storage_account_name at config-load time (regex ^[a-z0-9]{3,24}$).
- When using a custom environment, smoke-test the blob endpoint with curl before terraform init.
- Run with TF_LOG=DEBUG on first use of a new environment to print the resolved baseUri.
When it happens
Trigger: First lazy call to getBlobClient (during StateMgr / Workspaces / Put). The constructed base URL is malformed: a custom environment whose storage domain suffix is empty or non-HTTP, a private DNS blob endpoint that returned an invalid URL, or a storage_account_name containing characters illegal in a hostname.
Common situations: Sovereign cloud (US Gov / China) misconfigured via environment name; metadata_host pointing at an endpoint that returns malformed primaryEndpoints.blob; storage_account_name with underscores, uppercase letters, or trailing whitespace; private DNS zone setup.
Related errors
- new container client
- One of `access_key`, `sas_token`, `use_azuread_auth` and…
- populating details for
- auth must be one of ' ' or ' ' or ' ' or ' ' or ' ' or
- building Storage Accounts client: %+v
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/def9ae779dbd6a90.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/azure/api_client.go:148
var baseUri string
if c.accountDetail != nil {
// Use the actual blob endpoint if available
pBaseUri, err := c.accountDetail.DataPlaneEndpoint(EndpointTypeBlob)
if err != nil {
return nil, err
}
baseUri = *pBaseUri
} else {
baseUri, err = naiveStorageAccountBlobBaseURL(c.environment, c.storageAccountName)
if err != nil {
return nil, err
}
}
blobsClient, err := blobs.NewWithBaseUri(baseUri)
if err != nil {
return nil, fmt.Errorf("new blob client: %v", err)
}
switch {
case c.sasToken != "":
log.Printf("[DEBUG] Building the Blob Client from a SAS Token")
c.configureClient(blobsClient.Client, nil)
blobsClient.Client.AppendRequestMiddleware(func(r *http.Request) (*http.Request, error) {
if r.URL.RawQuery == "" {
r.URL.RawQuery = c.sasToken
} else if !strings.Contains(r.URL.RawQuery, c.sasToken) {
r.URL.RawQuery = fmt.Sprintf("%s&%s", r.URL.RawQuery, c.sasToken)
}
return r, nil
})
return blobsClient, nil
case c.accessKey != "":
log.Printf("[DEBUG] Building the Blob Client from an Access Key")View on GitHub (pinned to d32a084675)