hashicorp/terraform · error

unable to build authorizer for Resource Manager API: %+v

Error message

unable to build authorizer for Resource Manager API: %+v

What it means

Returned by buildClient when ARM authorizer is required (no access key/SAS/AAD-storage provided, or lookup_blob_endpoint=true) and auth.NewAuthorizerFromCredentials fails for the Resource Manager (management-plane) scope. The %+v wraps the underlying credential/auth error.

Source

Thrown at internal/backend/remote-state/azure/api_client.go:79

		var err error
		client.azureAdStorageAuth, err = auth.NewAuthorizerFromCredentials(ctx, *config.AuthConfig, config.AuthConfig.Environment.Storage)
		if err != nil {
			return nil, fmt.Errorf("unable to build authorizer for Storage API: %+v", err)
		}
	default:
		// AAD authentication (ARM scope) is required only when no auth method is specified, which falls back to listing the access key via ARM API.
		armAuthRequired = true
	}

	// If `config.LookupBlobEndpoint` is true, we need to authenticate with ARM to lookup the blob endpoint
	if config.LookupBlobEndpoint {
		armAuthRequired = true
	}

	if armAuthRequired {
		resourceManagerAuth, err := auth.NewAuthorizerFromCredentials(ctx, *config.AuthConfig, config.AuthConfig.Environment.ResourceManager)
		if err != nil {
			return nil, fmt.Errorf("unable to build authorizer for Resource Manager API: %+v", err)
		}

		// When using Azure CLI to auth, the user can leave the "subscription_id" unspecified. In this case the subscription id is inferred from
		// the Azure CLI default subscription.
		if config.SubscriptionID == "" {
			if cachedAuth, ok := resourceManagerAuth.(*auth.CachedAuthorizer); ok {
				if cliAuth, ok := cachedAuth.Source.(*auth.AzureCliAuthorizer); ok && cliAuth.DefaultSubscriptionID != "" {
					config.SubscriptionID = cliAuth.DefaultSubscriptionID
				}
			}
		}
		if config.SubscriptionID == "" {
			return nil, fmt.Errorf("subscription id not specified")
		}

		// Setup the SA client.
		client.storageAccountsClient, err = storageaccounts.NewStorageAccountsClientWithBaseURI(config.AuthConfig.Environment.ResourceManager)
		if err != nil {

View on GitHub (pinned to c9def3e214)

Solutions

  1. Provide valid ARM credentials: set ARM_CLIENT_ID, ARM_CLIENT_SECRET, ARM_TENANT_ID (or use ARM_USE_MSI=true / Azure CLI login).
  2. If using CLI auth, run 'az login' and ensure ARM_SUBSCRIPTION_ID/ARM_TENANT_ID are set or inferable.
  3. Set an explicit access_key or sas_token to avoid needing ARM auth entirely.
  4. Verify the cloud environment (ARM_ENVIRONMENT) matches where the principal exists.
Defensive patterns

Strategy: validation

Validate before calling

// When no explicit key/SAS, ARM creds are mandatory — check them up front.
if config.AccessKey == "" && config.SasToken == "" && !config.UseAzureADAuthentication {
    for _, k := range []string{"ARM_CLIENT_ID", "ARM_CLIENT_SECRET", "ARM_TENANT_ID"} {
        if os.Getenv(k) == "" { return fmt.Errorf("%s required for ARM auth", k) }
    }
}

Try / catch

client, err := buildClient(ctx, config)
if err != nil && strings.Contains(err.Error(), "build authorizer for Resource Manager") {
    // point to ARM credential / CLI login / network issues
}

Prevention

When it happens

Trigger: The Azure backend needs to call the ARM API (to list access keys or look up the blob endpoint) but cannot authenticate to Resource Manager. Fails during terraform init when building the client. Common when no explicit access key/SAS is given (default path) so Terraform must list keys via ARM.

Common situations: ARM_CLIENT_ID/SECRET/TENANT not set or expired; using Azure CLI auth in a session where 'az login' was not run or expired; MSI unavailable; network blocking login.microsoftonline.com; wrong cloud environment configured.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/ada27da49276adcf. Report an issue: GitHub.