VictoriaMetrics/VictoriaMetrics · error

cannot parse `iat` field: %w

Error message

cannot parse `iat` field: %w

What it means

Fires in the fastjson-based JWT claims parser when the optional 'iat' (issued-at) claim is present but not a valid integer. Input at fault is the iat field of the JWT payload; the token is structurally invalid and will be rejected.

Source

Thrown at lib/jwt/jwt.go:150

	}
	b.p = parserPool.Get()
	jv, err := b.p.ParseBytes(b.buf)
	if err != nil {
		return err
	}
	if jv.Type() != fastjson.TypeObject {
		return fmt.Errorf("unexpected non json object; type: %q", jv.Type())
	}
	if expObject := jv.Get("exp"); expObject != nil {
		b.Exp, err = expObject.Int64()
		if err != nil {
			return fmt.Errorf("cannot parse `exp` field: %w", err)
		}
	}
	if iatObject := jv.Get("iat"); iatObject != nil {
		b.Iat, err = iatObject.Int64()
		if err != nil {
			return fmt.Errorf("cannot parse `iat` field: %w", err)
		}
	}
	if issObject := jv.Get("iss"); issObject != nil {
		bIss, err := issObject.StringBytes()
		if err != nil {
			return fmt.Errorf("cannot parse `iss` field: %w", err)
		}
		b.Iss = bytesutil.ToUnsafeString(bIss)
	}

	vaObject := jv.Get("vm_access")
	switch {
	case vaObject == nil || vaObject.Type() == fastjson.TypeNull:
		b.hasVMAccess = false
	default:
		// some IDPs encode custom claims as a string
		// try parsing as an object and fallback to a string
		switch vaObject.Type() {

View on GitHub (pinned to 5079fb58f1)

Solutions

  1. Re-mint the token with `iat` as a JSON number of Unix seconds: {"iat": 1700000000}.
  2. Fix IDP claim transformation so iat is not stringified or date-formatted.
  3. Pre-validate the payload: decode the middle segment, check that iat is a number, and reject the token before Parse.
  4. Omit iat entirely if your token format doesn't need it — the parser only errors when the field exists.

Example fix

// before: iat as RFC3339 string
{ "iat": "2024-01-01T00:00:00Z" }
// after: iat as Unix seconds number
{ "iat": 1704067200 }
Defensive patterns

Strategy: validation

Validate before calling

func iatIsNumeric(seg string) bool {
	b, _ := base64.RawURLEncoding.DecodeString(strings.TrimRight(seg, "="))
	var v struct{ Iat any `json:"iat"` }
	if json.Unmarshal(b, &v) != nil { return false }
	_, ok := v.Iat.(float64)
	return ok
}

Type guard

func isNumericDate(v any) bool {
	_, ok := v.(float64)
	return ok
}

Try / catch

if err := t.Parse(src, enforcePrefix); err != nil {
	if strings.Contains(err.Error(), "cannot parse `iat` field") {
		// reject token: iat is not a NumericDate
	}
	return err
}

Prevention

When it happens

Trigger: Parsing a token whose payload contains e.g. "iat":"2024-01-01T00:00:00Z", "iat":1700000000.5 is fine but "iat":"1700000000" (string) or "iat":{} is not.

Common situations: IDPs with claim mappings that serialize iat as an ISO-8601 string; custom token generators using time.Time marshaled to RFC3339; hand-rolled test fixtures.

Related errors


AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03). Data as JSON: /api/errors/4ff0cc4d691f827b. Report an issue: GitHub.