ory/hydra · error · fosite.RFC6749Error
invalid_request
invalid_request
Error message
existing user code signature
What it means
CreateDeviceAuthSession wraps fosite.ErrExistingUserCodeSignature (hint "existing user code signature", code invalid_request) when the INSERT fails with a unique-violation error from the database. This means a device authorization row with the same user code signature already exists — user codes are random strings and a collision, or a duplicate submission, triggered the uniqueness constraint on the user_code signature column.
Source
Thrown at persistence/sql/persister_device.go:168
DeviceCodeActive: true,
UserCodeState: r.GetUserCodeState(),
}, nil
}
// CreateDeviceCodeSession creates a new device code session and stores it in the database. Implements DeviceAuthStorage.
func (p *Persister) CreateDeviceAuthSession(ctx context.Context, deviceCodeSignature, userCodeSignature string, requester fosite.DeviceRequester) (err error) {
ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.CreateDeviceCodeSession")
defer otelx.End(span, &err)
req, err := p.sqlDeviceSchemaFromRequest(ctx, deviceCodeSignature, userCodeSignature, requester, requester.GetSession().GetExpiresAt(fosite.DeviceCode).UTC())
if err != nil {
return err
}
if err := sqlcon.HandleError(p.CreateWithNetwork(ctx, req)); errors.Is(err, sqlcon.ErrConcurrentUpdate()) {
return errors.Wrap(fosite.ErrSerializationFailure, err.Error())
} else if errors.Is(err, sqlcon.ErrUniqueViolation()) {
return errors.Wrap(fosite.ErrExistingUserCodeSignature, err.Error())
} else if err != nil {
return err
}
return nil
}
// GetDeviceCodeSession returns a device code session from the database. Implements DeviceAuthStorage.
func (p *Persister) GetDeviceCodeSession(ctx context.Context, signature string, session fosite.Session) (_ fosite.DeviceRequester, err error) {
ctx, span := p.r.Tracer(ctx).Tracer().Start(ctx, "persistence.sql.GetDeviceCodeSession")
defer otelx.End(span, &err)
r := DeviceRequestSQL{}
if err = p.QueryWithNetwork(ctx).Where("device_code_signature = ?", signature).First(&r); errors.Is(err, sql.ErrNoRows) {
return nil, errors.WithStack(fosite.ErrNotFound)
} else if err != nil {
return nil, sqlcon.HandleError(err)
}View on GitHub (pinned to 4174065ffb)
Solutions
- Retry the device authorization request — the server generates a fresh random user code and the collision will (almost certainly) not repeat.
- If user codes are customizable/forced, ensure uniqueness before calling CreateDeviceAuthSession.
- Purge expired/stale device rows if the table is saturated with long-lived entries causing collisions.
- If seen in tests, use unique user codes per test case or clean the device table between runs.
Defensive patterns
Strategy: retry
Try / catch
if errors.Is(err, fosite.ErrExistingUserCodeSignature) {
// collision: regenerate user code / re-issue device authorization
} Prevention
- Let the server generate user codes from a large alphabet; avoid forcing/short codes.
- Clean expired device authorization rows periodically.
- In tests, use unique user codes and reset the device table between cases.
When it happens
Trigger: A generated 8-character user code collides with an existing, still-live device authorization row; calling the device authorization endpoint twice with the same forced user code; re-inserting a request after a retried transaction committed partially.
Common situations: Very small user code alphabets or custom short user codes increasing collision probability; tests that reuse the same user code across runs without cleanup; load tests replaying captured requests.
Related errors
- Expected request to be of type *Session, but got: %T
- server_error
- server_error
- device_challenge is required
- issuer URL must be set unless development mode is enabled
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/58091031fab91a75.
Report an issue: GitHub.