ory/hydra · error

Expected request to be of type *Session, but got: %T

Error message

Expected request to be of type *Session, but got: %T

What it means

sqlSchemaFromRequest (persistence/sql/persister_oauth2.go) converts a fosite Requester to a database row and requires the session to be the concrete *oauth2.Session type so it can persist ConsentChallenge. When GetSession() is non-nil but has a different Go type, it returns this error naming the offending type. This blocks createSession and CreateRefreshTokenSession from persisting the flow.

Source

Thrown at persistence/sql/persister_oauth2.go:259

	} else if err != nil {
		return err
	}

	return nil
}

func (p *Persister) sqlSchemaFromRequest(ctx context.Context, signature string, r fosite.Requester, table tableName, expiresAt time.Time) (*OAuth2RequestSQL, error) {
	subject := ""
	if r.GetSession() == nil {
		p.l.Debugf("Got an empty session in sqlSchemaFromRequest")
	} else {
		subject = r.GetSession().GetSubject()
	}

	var challenge sql.NullString
	rr, ok := r.GetSession().(*oauth2.Session)
	if !ok && r.GetSession() != nil {
		return nil, errors.Errorf("Expected request to be of type *Session, but got: %T", r.GetSession())
	} else if ok {
		if len(rr.ConsentChallenge) > 0 {
			challenge = sql.NullString{Valid: true, String: rr.ConsentChallenge}
		}
	}

	session, err := json.Marshal(rr)
	if err != nil {
		return nil, errors.WithStack(err)
	}

	if p.r.Config().EncryptSessionData(ctx) {
		ciphertext, err := p.r.KeyCipher().Encrypt(ctx, session, nil)
		if err != nil {
			return nil, err
		}
		session = []byte(ciphertext)
	}

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Ensure *oauth2.Session is used for all authorization-code/refresh-token requests (extend it for custom claims rather than replacing it).
  2. If a custom session type is required, also fork/adapt the SQL persister to handle it.
  3. Review config under oauth2.session / claims-mapping that installs a different session factory and align it with *oauth2.Session.
  4. Fix request-building code or tests to instantiate oauth2.NewSession(...).

Example fix

// before
request.SetSession(mySession{Subject: sub})
// after
sess := oauth2.NewSession(clientID)
sess.Subject = sub
request.SetSession(sess)
Defensive patterns

Strategy: type-guard

Type guard

func isOAuth2Session(r fosite.Requester) bool {
    _, ok := r.GetSession().(*oauth2.Session)
    return ok
}

Prevention

When it happens

Trigger: A custom session type registered via a claims/session extension (oauth2.session config, custom SessionStorage) flows into the authorization code or refresh token grant; manual construction of fosite requests with a different session struct; plugins/SDK code calling persister functions with foreign session objects.

Common situations: Projects customizing ID/access token claims with their own session struct and hitting refresh-token flows; forking Hydra and changing the session type without adapting the SQL persister; test fixtures using mock sessions.

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/3ea10dd9766a9fe1. Report an issue: GitHub.