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

  1. Retry the device authorization request — the server generates a fresh random user code and the collision will (almost certainly) not repeat.
  2. If user codes are customizable/forced, ensure uniqueness before calling CreateDeviceAuthSession.
  3. Purge expired/stale device rows if the table is saturated with long-lived entries causing collisions.
  4. 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

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


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