grpc/grpc-go · error
credentials: ctx cannot be nil
Error message
credentials: ctx cannot be nil
What it means
NewServiceAccountIdentityCredentials returns this when its ctx parameter is nil (gcp_service_account_identity_credentials.go:98-100). The context is stored on the credential and used for the lifetime of background token fetches, so a nil context cannot be tolerated. This is a hard programmer-error guard, not a runtime/network condition.
Source
Thrown at credentials/google/gcp_service_account_identity_credentials.go:99
// audience.
//
// This credential fetches the ID token from the GCE metadata server and is
// only valid for use in environments running on GCP. The ctx and audience
// parameters cannot be empty.
//
// The credentials object starts asynchronous background token fetches to
// refresh expired tokens. The provided context propagates cancellation to
// these background tasks. Users should not pass an RPC-scoped context here,
// 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
}View on GitHub (pinned to 03255a9237)
Solutions
- Pass a non-nil context — for long-lived creds use context.Background() (or a context you cancel at shutdown), never an RPC-scoped context.
- Add a nil-check in your own wiring code to fail at startup with a clearer message.
- If the context lifetime is unclear, pass context.Background() and manage shutdown via cancel.
Example fix
// before creds, err := google.NewServiceAccountIdentityCredentials(nil, aud) // after ctx, cancel := context.WithCancel(context.Background()) defer cancel() creds, err := google.NewServiceAccountIdentityCredentials(ctx, aud)
Defensive patterns
Strategy: validation
Validate before calling
// Validate context before constructing the credential.
if ctx == nil {
return nil, errors.New("caller bug: ctx is nil; pass context.Background()")
}
creds, err := google.NewServiceAccountIdentityCredentials(ctx, audience) Try / catch
creds, err := google.NewServiceAccountIdentityCredentials(ctx, aud)
if err != nil {
if strings.Contains(err.Error(), "ctx cannot be nil") {
// programmer error: fix the call site.
}
return nil, err
} Prevention
- Never pass nil context; use context.Background() for long-lived creds.
- Lint for nil-context arguments in credential construction.
- Thread context explicitly from a single owned root for credential lifetime.
When it happens
Trigger: Calling google.NewServiceAccountIdentityCredentials(nil, audience) — typically when a caller propagated an unset context variable, a constructor received nil from a parent struct, or a refactor forgot to thread context.Background().
Common situations: Initializing credentials in a package-level var before main wires up contexts, passing nil from a struct field defaulted to nil, or test scaffolding that did not pass a context.
Related errors
- credentials: audience cannot be empty
- credentials: failed to create ID token credentials: %v
- unsupported mode: %v
- token file %q: %v: %w
- no expiration claims
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/a9dfbcb8b6989341.
Report an issue: GitHub.