grpc/grpc-go · error

credentials: failed to create ID token credentials

Error message

credentials: failed to create ID token credentials: %v

What it means

Returned by NewServiceAccountIdentityCredentials when the underlying cloud.google.com/go/auth/credentials/idtoken.NewCredentials call fails to build an ID-token credential from the supplied audience. The wrapper preserves the root cause (e.g. malformed audience, missing/unreachable metadata server, invalid ADC) in the trailing %v. This credential type is only valid inside GCP, so the failure often reflects an environment mismatch rather than a programming error.

Solutions

  1. Verify the process runs on a GCE/GKE/Cloud Run/Flex App Engine instance where the metadata server is reachable (curl http://169.254.169.254).
  2. Confirm the audience string matches the intended target service's configured audience exactly (URL form, no trailing slash differences).
  3. Upgrade cloud.google.com/go/auth and google.golang.org/grpc to compatible versions and run go mod tidy.
  4. Inspect the wrapped error after the colon for the idtoken-specific root cause and address that directly.

Example fix

// before
creds, err := google.NewServiceAccountIdentityCredentials(context.Background(), "")
// after
creds, err := google.NewServiceAccountIdentityCredentials(ctx, "https://my-service-1234-uc.a.run.app")
if err != nil {
    return fmt.Errorf("build id-token creds: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

// Before calling NewServiceAccountIdentityCredentials, confirm the
// environment is GCP and the audience is well-formed.
func isOnGCP() bool {
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()
    _, err := metadata.GetWithContext(ctx, "instance/service-accounts/default/email")
    return err == nil
}

func validAudience(a string) bool {
    u, err := url.Parse(a)
    return err == nil && u.Scheme == "https" && u.Host != ""
}

if !isOnGCP() {
    log.Fatal("NewServiceAccountIdentityCredentials requires a GCP environment")
}
if !validAudience(audience) {
    log.Fatalf("invalid audience %q", audience)
}

Try / catch

creds, err := google.NewServiceAccountIdentityCredentials(ctx, audience)
if err != nil {
    return fmt.Errorf("id-token credential setup failed (are you on GCP? audience=%q): %w", audience, err)
}

Prevention

When it happens

Trigger: Calling google.NewServiceAccountIdentityCredentials(ctx, audience) outside of a GCP environment (no metadata server reachable at 169.254.169.254), passing a malformed audience string, or running with a broken/old google-auth library whose idtoken.NewCredentials returns a non-nil error at line 106-108.

Common situations: Running the binary locally or in a non-GCP CI worker where the GCE metadata server is unavailable; using an audience URL that does not match the target service's allowed audiences; pinning an incompatible cloud.google.com/go/auth version that changed the idtoken.Options contract.

Related errors


AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11). Data as JSON: /api/errors/8b517638ee211c95. Report an issue: GitHub.

Appendix: source

Thrown at credentials/google/gcp_service_account_identity_credentials.go:108

// but rather a context that is valid for the entire lifetime of the
// credentials and should cancel the context when they are done.
//
// # Experimental
//
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
// later release.
func NewServiceAccountIdentityCredentials(ctx context.Context, audience string) (credentials.PerRPCCredentials, error) {
	if ctx == nil {
		return nil, fmt.Errorf("credentials: ctx cannot be nil")
	}

	if audience == "" {
		return nil, fmt.Errorf("credentials: audience cannot be empty")
	}

	creds, err := internal.NewIDTokenCredentials(&idtoken.Options{Audience: audience})
	if err != nil {
		return nil, fmt.Errorf("credentials: failed to create ID token credentials: %v", err)
	}

	return &gcpServiceAccountIdentityCallCreds{
		ctx:      ctx,
		audience: audience,
		creds:    creds,
		backoff:  internal.BackoffStrategy,
	}, nil
}

// GetRequestMetadata gets the current request metadata, refreshing tokens if
// required. This implementation follows the PerRPCCredentials interface.
//
// It guarantees that only one underlying token fetch will be executed
// concurrently. If a valid token is cached, it is returned immediately. If
// a fetch recently failed, the cached error is returned until the backoff
// interval expires. Otherwise, it initiates a new token fetch or blocks
// waiting for an already-in-progress fetch to complete.

View on GitHub (pinned to 0c51461d27)