SigNoz/signoz · error · errors SigNozError

ErrCodeTokenRotationRequired

ErrCodeTokenRotationRequired

Error message

token needs to be rotated

What it means

Returned by Token.IsRotationRequired when RotatedAt is set but older than the rotation interval: the token was rotated before but is due again. Enforces periodic credential rotation.

Source

Thrown at pkg/types/authtypes/token.go:154

}

func (typ *Token) IsExpired(idleDuration time.Duration, maxDuration time.Duration) error {
	// If now - last_seen_at > idle_duration, the token will be considered as expired.
	if !typ.LastObservedAt.IsZero() && typ.LastObservedAt.Before(time.Now().Add(-idleDuration)) {
		return errors.New(errors.TypeUnauthenticated, ErrCodeTokenExpired, "token has not been used for too long")
	}

	// If now - created_at > max_duration, the token will be considered as expired.
	if typ.CreatedAt.Before(time.Now().Add(-maxDuration)) {
		return errors.New(errors.TypeUnauthenticated, ErrCodeTokenExpired, "token was created a long time ago")
	}

	return nil
}

func (typ *Token) IsRotationRequired(rotationInterval time.Duration) error {
	if !typ.RotatedAt.IsZero() && typ.RotatedAt.Before(time.Now().Add(-rotationInterval)) {
		return errors.New(errors.TypeUnauthenticated, ErrCodeTokenRotationRequired, "token needs to be rotated")
	}

	if typ.RotatedAt.IsZero() && typ.CreatedAt.Before(time.Now().Add(-rotationInterval)) {
		return errors.New(errors.TypeUnauthenticated, ErrCodeTokenRotationRequired, "token needs to be rotated")
	}

	return nil
}

func (typ *Token) Rotate(accessTokenOrPrevAccessToken string, refreshTokenOrPrevRefreshToken string, rotationDuration time.Duration, idleDuration time.Duration, maxDuration time.Duration) error {
	if typ.PrevAccessToken == accessTokenOrPrevAccessToken && typ.PrevRefreshToken == refreshTokenOrPrevRefreshToken {
		// If the token has been rotated within the rotation duration, do nothing and return the same token.
		if !typ.RotatedAt.IsZero() && typ.RotatedAt.Before(time.Now().Add(-rotationDuration)) {
			return nil
		}

		return errors.New(errors.TypeUnauthenticated, errors.CodeUnauthenticated, "invalid token pair")
	}

View on GitHub (pinned to 5069bf80b0)

Solutions

  1. Call the rotate endpoint with the current token pair to get a rotated token
  2. Schedule rotation at intervals shorter than rotationInterval
  3. Update SDK/client that caches tokens without rotating them
Defensive patterns

Strategy: retry

Validate before calling

if !tok.RotatedAt.IsZero() && time.Since(tok.RotatedAt) > rotationInterval { /* rotate now */ }

Try / catch

if err := tok.IsRotationRequired(interval); err != nil { /* call rotate endpoint with current pair, then retry original call */ }

Prevention

When it happens

Trigger: Calling IsValid on a token whose rotatedAt is older than now minus rotationInterval.

Common situations: Client keeps using an access/refresh token pair past the rotation window without calling the rotate endpoint.

Related errors


AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28). Data as JSON: /api/errors/0c80deea53677dbc. Report an issue: GitHub.