{"record":{"id":"0e3291b699b0e090","repo":"ory/hydra","slug":"expected-request-to-be-of-type-session-but-got","errorCode":null,"errorMessage":"Expected request to be of type *Session, but got: %T","messagePattern":"Expected request to be of type \\*Session, but got: %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"persistence/sql/persister_device.go","lineNumber":128,"sourceCode":"\t}\n\n\tsession, err := json.Marshal(r.GetSession())\n\tif err != nil {\n\t\treturn nil, errors.WithStack(err)\n\t}\n\n\tif p.r.Config().EncryptSessionData(ctx) {\n\t\tciphertext, err := p.r.KeyCipher().Encrypt(ctx, session, nil)\n\t\tif err != nil {\n\t\t\treturn nil, errors.WithStack(err)\n\t\t}\n\t\tsession = []byte(ciphertext)\n\t}\n\n\tvar challenge sql.NullString\n\trr, ok := r.GetSession().(*oauth2.Session)\n\tif !ok && r.GetSession() != nil {\n\t\treturn nil, errors.Errorf(\"Expected request to be of type *Session, but got: %T\", r.GetSession())\n\t} else if ok {\n\t\tif len(rr.ConsentChallenge) > 0 {\n\t\t\tchallenge = sql.NullString{Valid: true, String: rr.ConsentChallenge}\n\t\t}\n\t}\n\n\treturn &DeviceRequestSQL{\n\t\tRequest:           r.GetID(),\n\t\tConsentChallenge:  challenge,\n\t\tID:                deviceCodeSignature,\n\t\tUserCodeID:        userCodeSignature,\n\t\tRequestedAt:       r.GetRequestedAt(),\n\t\tInternalExpiresAt: sqlxx.NullTime(expiresAt),\n\t\tClient:            r.GetClient().GetID(),\n\t\tScopes:            strings.Join(r.GetRequestedScopes(), \"|\"),\n\t\tGrantedScope:      strings.Join(r.GetGrantedScopes(), \"|\"),\n\t\tGrantedAudience:   strings.Join(r.GetGrantedAudience(), \"|\"),\n\t\tRequestedAudience: strings.Join(r.GetRequestedAudience(), \"|\"),","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/persistence/sql/persister_device.go#L110-L146","documentation":"sqlDeviceSchemaFromRequest converts a fosite Requester into a database row and expects the attached session to be of the concrete type *oauth2.Session (so it can read ConsentChallenge). If GetSession() returns a non-nil value of any other Go type, it returns this error with the actual %T type name. It indicates that a custom session implementation was plugged into the OAuth2 flow but the SQL persister cannot serialize it for the device code flow.","triggerScenarios":"Registering a custom session type via config (oauth2.session.establish_session or a custom SessionStorage/transform extension) and then calling CreateDeviceAuthSession or UpdateDeviceCodeSessionBySignature with that request; running device authorization flow while a custom JWT/session claims extension swapped the session type.","commonSituations":"Projects that customize access/id token claims with their own session struct but later enable the device flow; integration code that constructs a fosite request manually with the wrong session type; tests passing a mock session into the persister.","solutions":["Make the session passed into the device flow an instance of *oauth2.Session (or embed and convert it before calling the persister).","If using a custom session for claim extension, keep the consent challenge accessible by wrapping/converting to *oauth2.Session before persistence.","Check config for custom session/claim extensions (e.g. oauth2.session) and remove or adapt them when using the device code flow.","Fix test/integration harnesses to construct requests with the correct session type."],"exampleFix":"// before\nreq.SetSession(&myCustomSession{Subject: \"user\"})\n// after\nsess := oauth2.NewSession(\"client-id\")\nsess.Subject = \"user\"\nreq.SetSession(sess)","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isOAuth2Session(r fosite.Requester) bool {\n    _, ok := r.GetSession().(*oauth2.Session)\n    return ok\n}\n// call before invoking CreateDeviceAuthSession","tryCatchPattern":null,"preventionTips":["Always build device-flow requests with oauth2.NewSession.","Extend *oauth2.Session for custom claims instead of substituting a new type.","Audit any config that installs a custom session factory when using the device code flow."],"tags":["go","type-mismatch","oauth2","device-flow"],"backgroundTag":"unexpected-session-type","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}