go-kit/kit · error · ErrTokenMalformed
JWT is malformed
Error message
JWT is malformed
What it means
Returned by jwt.NewParser when the underlying jwt.ValidationError has the ValidationErrorMalformed bit set: the string pulled from the context is not parseable as a JWT at all. A valid JWT is three dot-separated base64url segments; anything else fails immediately.
Source
Thrown at auth/jwt/middleware.go:39
// JWTClaimsContextKey holds the key used to store the JWT Claims in the
// context.
JWTClaimsContextKey contextKey = "JWTClaims"
)
var (
// ErrTokenContextMissing denotes a token was not passed into the parsing
// middleware's context.
ErrTokenContextMissing = errors.New("token up for parsing was not passed through the context")
// ErrTokenInvalid denotes a token was not able to be validated.
ErrTokenInvalid = errors.New("JWT was invalid")
// ErrTokenExpired denotes a token's expire header (exp) has since passed.
ErrTokenExpired = errors.New("JWT is expired")
// ErrTokenMalformed denotes a token was not formatted as a JWT.
ErrTokenMalformed = errors.New("JWT is malformed")
// ErrTokenNotActive denotes a token's not before header (nbf) is in the
// future.
ErrTokenNotActive = errors.New("token is not valid yet")
// ErrUnexpectedSigningMethod denotes a token was signed with an unexpected
// signing method.
ErrUnexpectedSigningMethod = errors.New("unexpected signing method")
)
// NewSigner creates a new JWT generating middleware, specifying key ID,
// signing string, signing method and the claims you would like it to contain.
// Tokens are signed with a Key ID header (kid) which is useful for determining
// the key to use for parsing. Particularly useful for clients.
func NewSigner(kid string, key []byte, method jwt.SigningMethod, claims jwt.Claims) endpoint.Middleware {
return func(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
token := jwt.NewWithClaims(method, claims)View on GitHub (pinned to 78fbbceece)
Solutions
- Strip the auth scheme before storing: strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ")
- Reject/401 early when the header is empty or lacks the Bearer scheme so garbage never reaches the parser
- Verify the token has the shape header.payload.signature (two dots, non-empty segments) before invoking the endpoint
- Regenerate/copy the token cleanly if it was truncated or mangled
Example fix
// before: whole header, "Bearer " included, stored as the token
return context.WithValue(ctx, jwt.JWTContextKey, r.Header.Get("Authorization"))
// after: store only the bare token
v := strings.TrimSpace(r.Header.Get("Authorization"))
v = strings.TrimPrefix(v, "Bearer ")
if v == "" {
return ctx // parser will surface the missing/malformed error as 401
}
return context.WithValue(ctx, jwt.JWTContextKey, v) Defensive patterns
Strategy: try-catch
Validate before calling
func looksLikeJWT(s string) bool {
parts := strings.Split(s, ".")
return len(parts) == 3 && parts[0] != "" && parts[1] != "" && parts[2] != ""
}
// apply to the value before storing it in jwt.JWTContextKey Type guard
null
Try / catch
if _, err := ep(ctx, req); err != nil {
if errors.Is(err, jwt.ErrTokenMalformed) {
// 400/401: the client is not sending a real JWT — fix the sender, no retry
}
} Prevention
- Strip the Bearer prefix exactly once, in one shared RequestFunc
- Validate the 3-segment shape at the transport boundary and reject early with 400
- Never pass tokens through logs/shell copy-paste; move them via secret managers or headers only
When it happens
Trigger: Storing the entire Authorization header, including the "Bearer " prefix, in jwt.JWTContextKey instead of the bare token; an empty string when the header is missing; a token truncated by logging/truncation or mangled by URL encoding; garbage values from a misconfigured proxy or a hand-built test context.
Common situations: RequestFunc forgets strings.TrimPrefix(header, "Bearer "); clients sending a raw API key or session id where a JWT is expected; copy-paste of tokens with newlines/quotes from terminal; gateways rewriting or double-encoding the Authorization header.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- token up for parsing was not passed through the context
- JWT was invalid
- JWT is expired
- token is not valid yet
- unexpected signing method
AI-assisted analysis of go-kit/kit@78fbbceece (2026-08-15).
Data as JSON: /api/errors/910a21744d53a027.
Report an issue: GitHub.