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
- Ensure *oauth2.Session is used for all authorization-code/refresh-token requests (extend it for custom claims rather than replacing it).
- If a custom session type is required, also fork/adapt the SQL persister to handle it.
- Review config under oauth2.session / claims-mapping that installs a different session factory and align it with *oauth2.Session.
- 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
- Use *oauth2.Session for all code/refresh grant requests; extend it for custom claims.
- If forking, adapt the SQL persister together with any custom session type.
- Keep test fixtures on the real oauth2.Session type or add the guard above in harnesses.
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
- Expected request to be of type *Session, but got: %T
- issuer URL must be set unless development mode is enabled
- issuer URL scheme must be HTTPS unless development mode is e
- failed to set token lifespans due to failed client type asse
- a secret for signing HMAC-SHA512/256 is expected to be defin
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/3ea10dd9766a9fe1.
Report an issue: GitHub.