grpc/grpc-go · error

failed to unmarshal JWT call credentials config: %v

Error message

failed to unmarshal JWT call credentials config: %v

What it means

jwtcreds.NewCallCredentials (call_creds.go:43-44) unmarshals the provided json.RawMessage into a struct expecting a single jwt_token_file string field. If the JSON is syntactically invalid or contains values of the wrong type, encoding/json fails and the error is wrapped here. This is the JWT call-credentials plugin for xDS bootstrap (gRFC A97).

Source

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

	"fmt"

	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/credentials/jwt"
)

// NewCallCredentials returns a new JWT token based call credentials. The input
// 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 03255a9237)

Solutions

  1. Validate that the call_credentials config value is a JSON object with a string jwt_token_file field.
  2. Use jq or a JSON validator on the specific credentials sub-document.
  3. Ensure templating engines quote file paths correctly when injecting them.

Example fix

// before:
//   { "type": "jwt", "config": { jwt_token_file: /etc/tokens/jwt } }
// after:
//   { "type": "jwt", "config": { "jwt_token_file": "/etc/tokens/jwt" } }
Defensive patterns

Strategy: validation

Validate before calling

// Validate the JWT creds config JSON before passing to NewCallCredentials.
func validateJWTCredsConfig(cfg json.RawMessage) error {
    var probe struct{ JWTTokenFile string `json:"jwt_token_file"` }
    if err := json.Unmarshal(cfg, &probe); err != nil {
        return fmt.Errorf("jwt creds config not valid JSON: %w", err)
    }
    return nil
}

Prevention

When it happens

Trigger: The bootstrap references a call_credentials block of type whose config blob is malformed JSON, or the config object has jwt_token_file set to a non-string value. Any json.Unmarshal failure on the config JSON triggers this.

Common situations: The call_creds config was templated with an unquoted variable; the config field was accidentally left as a JSON object instead of a string; a typo introduced invalid JSON syntax in the credentials sub-document.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/7992f3bd9183f029. Report an issue: GitHub.