multica-ai/multica · error

invalid claims

Error message

invalid claims

What it means

HTTP 401 returned when the parsed JWT's claims cannot be asserted as jwt.MapClaims. With golang-jwt this is nearly unreachable for tokens parsed with the default parser (MapClaims is the default claims type); hitting it means the parser was configured with a custom claims factory or the token is structurally degenerate. It signals the claim-extraction contract is broken, not that values inside the claims are wrong.

Source

Thrown at server/internal/middleware/auth.go:218

			}

			// JWT
			token, err := jwt.Parse(tokenString, func(token *jwt.Token) (any, error) {
				if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
					return nil, jwt.ErrSignatureInvalid
				}
				return auth.JWTSecret(), nil
			})
			if err != nil || !token.Valid {
				slog.Warn("auth: invalid token", "path", r.URL.Path, "error", err)
				http.Error(w, `{"error":"invalid token"}`, http.StatusUnauthorized)
				return
			}

			claims, ok := token.Claims.(jwt.MapClaims)
			if !ok {
				slog.Warn("auth: invalid claims", "path", r.URL.Path)
				http.Error(w, `{"error":"invalid claims"}`, http.StatusUnauthorized)
				return
			}

			sub, ok := claims["sub"].(string)
			if !ok || strings.TrimSpace(sub) == "" {
				slog.Warn("auth: invalid claims", "path", r.URL.Path)
				http.Error(w, `{"error":"invalid claims"}`, http.StatusUnauthorized)
				return
			}
			r.Header.Set("X-User-ID", sub)
			if email, ok := claims["email"].(string); ok {
				r.Header.Set("X-User-Email", email)
			}

			next.ServeHTTP(w, r)
		})
	}
}

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Issue tokens through the standard login flow so claims are standard JSON objects.
  2. If you control parsing, use the default parser (MapClaims) upstream of this middleware.
  3. Regenerate the token — a structurally valid login-issued JWT will not hit this branch.
  4. Check for library version drift in go.mod if this appears after an upgrade.
Defensive patterns

Strategy: type-guard

Type guard

func hasMapClaims(tok string) bool {
    t, _, err := jwt.NewParser().ParseUnverified(tok, jwt.MapClaims{})
    return err == nil && t != nil
}

Try / catch

resp, err := client.Do(req)
if err == nil && resp.StatusCode == 401 {
    body, _ := io.ReadAll(resp.Body)
    if strings.Contains(string(body), "invalid claims") { tok = relogin() } // token shape wrong, not secret wrong
}

Prevention

When it happens

Trigger: Token parsed with a Parser configured to use a custom ClaimFactory returning a non-MapClaims type, or an edge-case token that yields nil claims; then this middleware's MapClaims assertion fails.

Common situations: Library version change altering parser defaults; a shared parsing helper configured elsewhere with custom claims; malformed token crafted to have an empty payload.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/bd46dfd91d0d5bfe. Report an issue: GitHub.