ory/hydra · error
flow ForceSubjectIdentifier %s does not match the HandledLog
Error message
flow ForceSubjectIdentifier %s does not match the HandledLoginRequest ForceSubjectIdentifier %s
What it means
Flow.HandleLoginRequest also verifies ForceSubjectIdentifier: if both the Flow and the HandledLoginRequest carry a non-empty ForceSubjectIdentifier they must be identical. This field is set when an upstream flow (e.g. a previous authentication or ID token hint) forced a specific subject, and mismatch means the login was accepted for a different identity than forced.
Source
Thrown at flow/flow.go:314
func (f *Flow) InvalidateDeviceRequest() error {
if err := f.State.IsAny(DeviceFlowStateUnused); err != nil {
return err
}
f.State = DeviceFlowStateUsed
return nil
}
func (f *Flow) HandleLoginRequest(h *HandledLoginRequest) error {
if err := f.State.IsAny(FlowStateLoginInitialized, FlowStateLoginUnused, FlowStateLoginError); err != nil {
return err
}
if f.Subject != "" && h.Subject != "" && f.Subject != h.Subject {
return errors.Errorf("flow Subject %s does not match the HandledLoginRequest Subject %s", f.Subject, h.Subject)
}
if f.ForceSubjectIdentifier != "" && h.ForceSubjectIdentifier != "" && f.ForceSubjectIdentifier != h.ForceSubjectIdentifier {
return errors.Errorf("flow ForceSubjectIdentifier %s does not match the HandledLoginRequest ForceSubjectIdentifier %s", f.ForceSubjectIdentifier, h.ForceSubjectIdentifier)
}
f.State = FlowStateLoginUnused
if f.Context != nil {
f.Context = h.Context
}
f.Subject = h.Subject
f.ForceSubjectIdentifier = h.ForceSubjectIdentifier
f.IdentityProviderSessionID = sqlxx.NullString(h.IdentityProviderSessionID)
f.LoginRemember = h.Remember
f.LoginRememberFor = h.RememberFor
f.LoginExtendSessionLifespan = h.ExtendSessionLifespan
f.ACR = h.ACR
f.AMR = h.AMR
return nilView on GitHub (pinned to 4174065ffb)
Solutions
- Make the login provider enforce the forced subject (auto-select/pre-authenticate that user) so h.ForceSubjectIdentifier matches the flow
- If the forced subject cannot be satisfied, fail the login with an error instead of accepting a different identity
- If forcing is no longer desired, create a new login flow without ForceSubjectIdentifier set
- Verify you are not copying fields from a different flow into the HandledLoginRequest
Example fix
// before
handled := &flow.HandledLoginRequest{Subject: session.Subject, ForceSubjectIdentifier: session.Subject}
err := flow.HandleLoginRequest(handled)
// after
if flow.ForceSubjectIdentifier != "" && flow.ForceSubjectIdentifier != session.Subject {
return errors.New("forced subject does not match authenticated user") // reject login
}
handled.ForceSubjectIdentifier = flow.ForceSubjectIdentifier
err := flow.HandleLoginRequest(handled) Defensive patterns
Strategy: validation
Validate before calling
if flow.ForceSubjectIdentifier != "" {
if session.Subject != flow.ForceSubjectIdentifier {
return errors.New("forced subject mismatch: user must re-authenticate as the forced identity")
}
handled.ForceSubjectIdentifier = flow.ForceSubjectIdentifier
}
err := flow.HandleLoginRequest(handled) Try / catch
if err := flow.HandleLoginRequest(handled); err != nil {
if strings.Contains(err.Error(), "ForceSubjectIdentifier") {
return redirectToLoginWithError("please authenticate with the required account")
}
return err
} Prevention
- When a flow carries ForceSubjectIdentifier, enforce single-sign-on/auto-login for exactly that subject
- Never let the login UI allow choosing a different account when a subject is forced (use max_age/prompt=none semantics)
- Propagate the forced subject through your login provider instead of regenerating it from the current session
- Test the id_token_hint flow with a session for a different user to catch mismatches
When it happens
Trigger: Calling HandleLoginRequest when f.ForceSubjectIdentifier and h.ForceSubjectIdentifier are both set but differ — typically when id_token_hint or a forced subject from an earlier step conflicts with the user that actually authenticated.
Common situations: Using id_token_hint for silent re-authentication but the session belongs to another user; a subject was forced by consent/previous authentication but the login handler let the user log in with a different account; mixing flow objects between requests.
Related errors
- flow Subject %s does not match the HandledLoginRequest Subje
- issuer URL must be set unless development mode is enabled
- Only access tokens are allowed in the authorization header.
- invalid flow state: expected one of %v, got %d
- issuer URL scheme must be HTTPS unless development mode is e
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/0590619ee78d549b.
Report an issue: GitHub.