grpc/grpc-go · error

failed to create JWT call credentials

Error message

failed to create JWT call credentials: %v

What it means

Returned by jwtcreds.NewCallCredentials when jwt.NewTokenFileCallCredentials fails for the supplied file path. The underlying error from the JWT package is wrapped.

Solutions

  1. Verify the path exists and is readable: ls -l /var/secrets/token.jwt.
  2. Inspect the underlying %v error to distinguish missing-file vs parse failure.
  3. Confirm the file contents is a valid compact-serialization JWT (three base64url segments separated by '.').
  4. In containers, ensure the secret holding the token is mounted at that path.

Example fix

# before: file missing or unreadable
{"jwt_token_file":"/var/secrets/token.jwt"}
# ls /var/secrets/token.jwt -> No such file

# after: create/mount the token
echo -n 'eyJhbGciOi...signature' > /var/secrets/token.jwt
chmod 600 /var/secrets/token.jwt
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight check of the JWT token file before bootstrap.
func checkJWTTokenFile(path string) error {
    fi, err := os.Stat(path)
    if err != nil {
        return fmt.Errorf("jwt token file: %w", err)
    }
    if fi.Size() == 0 {
        return fmt.Errorf("jwt token file is empty")
    }
    return nil
}

Try / catch

if _, _, err := jwtcreds.NewCallCredentials(cfg); err != nil {
    if strings.Contains(err.Error(), "failed to create JWT call credentials") {
        // verify file exists/permissions/contents, then retry.
    }
}

Prevention

When it happens

Trigger: Triggered at call_creds.go:51 when jwt.NewTokenFileCallCredentials(cfg.JWTTokenFile) errors. Typically the file cannot be read or cannot be parsed.

Common situations: Token file does not exist at the given path; permission denied; file is empty or not a valid JWT (wrong number of segments, bad base64); path is correct in dev but not mounted in the container.

Related errors


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

Appendix: source

Thrown at internal/xds/bootstrap/jwtcreds/call_creds.go:51

// config must match the structure specified in gRFC A97.
//
// The caller is expected to invoke the cancel function when they are done using
// the returned call creds. This cancel function is idempotent.
func NewCallCredentials(configJSON json.RawMessage) (c credentials.PerRPCCredentials, cancel func(), err error) {
	var cfg struct {
		JWTTokenFile string `json:"jwt_token_file"`
	}
	emptyFn := func() {}

	if err := json.Unmarshal(configJSON, &cfg); err != nil {
		return nil, emptyFn, fmt.Errorf("failed to unmarshal JWT call credentials config: %v", err)
	}
	if cfg.JWTTokenFile == "" {
		return nil, emptyFn, fmt.Errorf("jwt_token_file is required in JWT call credentials config")
	}
	callCreds, err := jwt.NewTokenFileCallCredentials(cfg.JWTTokenFile)
	if err != nil {
		return nil, emptyFn, fmt.Errorf("failed to create JWT call credentials: %v", err)
	}
	return callCreds, emptyFn, nil
}

View on GitHub (pinned to 0c51461d27)