hashicorp/terraform · error

storage.NewClient() failed

Error message

storage.NewClient() failed: %v

What it means

Thrown when the Google Cloud Storage client constructor returns an error. By this point credential options, user agent, and any custom endpoint have been assembled into opts; storage.NewClient(ctx, opts...) failing means authentication, transport, or endpoint configuration is invalid.

Solutions

  1. Run `gcloud auth application-default login` (or set GOOGLE_APPLICATION_CREDENTIALS) and retry.
  2. Inspect the wrapped %v error in the message — it names the real cause (e.g., 'cannot find credentials').
  3. Remove or correct storage_custom_endpoint if it points at a non-GCS service.
  4. Verify outbound network access to oauth2.googleapis.com and storage.googleapis.com.

Example fix

// before — no credentials in CI
// after
gcloud auth application-default login --backend=no  # or set GOOGLE_APPLICATION_CREDENTIALS
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight ADC check before invoking terraform.
// `gcloud auth application-default print-access-token` returns non-zero if ADC is missing.

Try / catch

// Retry transient client-creation failures with backoff.
var client *storage.Client
var err error
for i := 0; i < 3; i++ {
    client, err = storage.NewClient(ctx, opts...)
    if err == nil { break }
    if isPermAuthErr(err) { break } // don't retry bad creds
    time.Sleep(backoff(i))
}

Prevention

When it happens

Trigger: storage.NewClient returns a non-nil error — invalid credentials JSON format accepted earlier but rejected by the token endpoint, no application-default credentials available, unreachable custom endpoint, or system clock skew breaking the OAuth exchange.

Common situations: Running terraform in CI without GOOGLE_APPLICATION_CREDENTIALS or workload identity; pointing storage_custom_endpoint at a URL that returns non-OAuth responses; the ADC metadata server is unreachable from the VM; transient network failure reaching googleapis.com.

Related errors


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

Appendix: source

Thrown at internal/backend/remote-state/gcs/backend.go:256

		}

		opts = append(opts, option.WithTokenSource(ts))

	} else {
		opts = append(opts, credOptions...)
	}

	opts = append(opts, option.WithUserAgent(httpclient.UserAgentString()))

	// Custom endpoint for storage API
	if storageEndpoint := data.String("storage_custom_endpoint"); storageEndpoint != "" {
		endpoint := option.WithEndpoint(storageEndpoint)
		opts = append(opts, endpoint)
	}
	client, err := storage.NewClient(ctx, opts...)
	if err != nil {
		return backendbase.ErrorAsDiagnostics(
			fmt.Errorf("storage.NewClient() failed: %v", err),
		)
	}

	b.storageClient = client

	// Customer-supplied encryption
	key := data.String("encryption_key")
	if key != "" {
		kc, err := readPathOrContents(key)
		if err != nil {
			return backendbase.ErrorAsDiagnostics(
				fmt.Errorf("Error loading encryption key: %s", err),
			)
		}

		// The GCS client expects a customer supplied encryption key to be
		// passed in as a 32 byte long byte slice. The byte slice is base64
		// encoded before being passed to the API. We take a base64 encoded key

View on GitHub (pinned to d32a084675)