kataras/iris · error

refresh: %w

Error message

refresh: %w

What it means

This error wraps any failure that occurs while signing the refresh token inside Auth.sign(). It only fires when refresh tokens are enabled, i.e. the configuration's Keys contain a KIDRefresh key. The underlying error comes from the JWT signer (Key.SignToken), typically a bad or unusable key.

Source

Thrown at auth/auth.go:303

	}

	if refreshStdClaims.OriginID == "" {
		// keep a reference of the access token the refresh token is created,
		// if that access token is invalidated then
		// its refresh token should be too so the user can force-login.
		refreshStdClaims.OriginID = accessStdClaims.ID
	}

	accessToken, err := s.keys.SignToken(KIDAccess, t, accessStdClaims)
	if err != nil {
		return nil, nil, fmt.Errorf("access: %w", err)
	}

	var refreshToken []byte
	if s.refreshEnabled {
		refreshToken, err = s.keys.SignToken(KIDRefresh, t, refreshStdClaims)
		if err != nil {
			return nil, nil, fmt.Errorf("refresh: %w", err)
		}
	}

	return accessToken, refreshToken, nil
}

// SignHandler generates and sends a pair of access and refresh token to the client
// as JSON body of `SigninResponse` and cookie (if cookie setting was provided).
// See `Signin` method for more.
func (s *Auth[T]) SigninHandler(ctx *context.Context) {
	// No, let the developer decide it based on a middleware, e.g. iris.LimitRequestBodySize.
	// ctx.SetMaxRequestBodySize(s.maxRequestBodySize)

	var (
		req SigninRequest
		err error
	)

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Inspect the wrapped %w error to find the exact SignToken failure
  2. Verify the KIDRefresh key material is valid and matches the configured algorithm
  3. Confirm the KIDRefresh key type (HMAC secret vs RSA/ECDSA private key) matches c.Keys configuration
  4. If refresh tokens are not needed, remove KIDRefresh from Keys so the refresh path is skipped

Example fix

// before
Keys: map[string]jwt.Key{ "access": []byte("short"), "refresh": "" }
// after
Keys: map[string]jwt.Key{ "access": []byte(longRandomSecret), "refresh": []byte(anotherLongRandomSecret) }
Defensive patterns

Strategy: try-catch

Validate before calling

for kid := range map[string][]byte{"access": accessKey, "refresh": refreshKey} {
    if len(k[kid]) == 0 { return fmt.Errorf("empty key material for %s", kid) }
}

Try / catch

access, refresh, err := auth.Signin(ctx, username, password)
if err != nil {
    var cfgErr interface{ Unwrap() error }
    if errors.Is(err, jwt.ErrKeyMismatch) { /* fix key config */ }
    return fmt.Errorf("signin failed: %w", err)
}

Prevention

When it happens

Trigger: s.refreshEnabled is true (a KIDRefresh key was configured) and s.keys.SignToken(KIDRefresh, t, refreshStdClaims) returns an error — e.g. the refresh key bytes are invalid, the algorithm and key type mismatch, or the key store fails to produce a signed token. Reached via Signin or Refresh.

Common situations: A KIDRefresh entry was added to config.Keys with malformed or too-short key material, an RSA key supplied where HMAC is expected, or a key file/env value that fails to parse during SignToken.

Related errors


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