kataras/iris · error

refresh max age should be bigger than access token's one[%d

Error message

refresh max age should be bigger than access token's one[%d - %d]

What it means

iris-jwt's Signer.NewTokenPair requires the refresh token's MaxAge (refreshMaxAge) to be strictly greater than the access token's configured MaxAge (s.MaxAge). The guard prevents creating a pair where the refresh token expires before or exactly when the access token does, which would make refresh flows useless. The error message prints both durations.

Source

Thrown at middleware/jwt/signer.go:84

}

// Sign generates a new token based on the given "claims" which is valid up to "s.MaxAge".
func (s *Signer) Sign(claims any, opts ...SignOption) ([]byte, error) {
	if len(opts) > 0 {
		opts = append(opts, s.Options...)
	} else {
		opts = s.Options
	}

	return SignEncrypted(s.Alg, s.Key, s.Encrypt, claims, opts...)
}

// NewTokenPair accepts the access and refresh claims plus the life time duration for the refresh token
// and generates a new token pair which can be sent to the client.
// The same token pair can be json-decoded.
func (s *Signer) NewTokenPair(accessClaims any, refreshClaims any, refreshMaxAge time.Duration, accessOpts ...SignOption) (TokenPair, error) {
	if refreshMaxAge <= s.MaxAge {
		return TokenPair{}, fmt.Errorf("refresh max age should be bigger than access token's one[%d - %d]", refreshMaxAge, s.MaxAge)
	}

	accessToken, err := s.Sign(accessClaims, accessOpts...)
	if err != nil {
		return TokenPair{}, err
	}

	refreshToken, err := Sign(s.Alg, s.Key, refreshClaims, MaxAge(refreshMaxAge))
	if err != nil {
		return TokenPair{}, err
	}

	tokenPair := jwt.NewTokenPair(accessToken, refreshToken)
	return tokenPair, nil
}

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Pass a refreshMaxAge clearly larger than the signer's MaxAge (e.g. access 15m, refresh 7*24h).
  2. Review the Signer's MaxAge configuration (WithMaxAge) and pick refreshMaxAge relative to it, not equal to it.
  3. If you intended refreshMaxAge as a timestamp, note it is a time.Duration from now; convert accordingly.

Example fix

// before
signer.MaxAge = 15 * time.Minute
pair, err := signer.NewTokenPair(access, refresh, 15*time.Minute) // error

// after
pair, err := signer.NewTokenPair(access, refresh, 7*24*time.Hour) // refresh outlives access
Defensive patterns

Strategy: validation

Validate before calling

if refreshMaxAge <= signer.MaxAge { return errors.New("refreshMaxAge must exceed access MaxAge") }

Type guard

func validTokenPairDurations(refresh, access time.Duration) bool { return refresh > access }

Try / catch

pair, err := signer.NewTokenPair(ac, rc, refreshMaxAge); if err != nil && strings.Contains(err.Error(), "refresh max age") { return fmt.Errorf("config: %w", err) }

Prevention

When it happens

Trigger: Calling signer.NewTokenPair(accessClaims, refreshClaims, refreshMaxAge) where refreshMaxAge <= s.MaxAge, e.g. both set to 15 minutes, or refreshMaxAge equal to the access lifetime.

Common situations: Misreading refreshMaxAge as an absolute timestamp instead of a duration, copying the same constant for both lifetimes, or lowering Signer MaxAge in config after hardcoding a refresh duration.

Related errors


AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30). Data as JSON: /api/errors/74b88aeee6b1888d. Report an issue: GitHub.