ory/kratos · warning
verification requested for unknown address
Error message
verification requested for unknown address
What it means
ErrUnknownAddress in link/sender.go is a 404-style herodot error raised when a recovery or verification flow requests a send to an address that does not correspond to any known identity. It is deliberately generic to prevent account enumeration (the code package exposes an equivalent `recovery requested for unknown address` variant).
Solutions
- Show the user a generic 'if the address exists we sent an email' message (the API already returns this to avoid enumeration)
- Verify the address used matches an existing, active identity's verifiable address in the admin API
- Re-register the account or use a different recovery path if the identity truly does not exist
- For integrations, check GET /admin/identities?credentials_identifier=... before programmatically triggering sends
Example fix
// before
POST /self-service/recovery {"email": "typo@exmaple.com"}
// after
POST /self-service/recovery {"email": "user@example.com"} // address must match a known identity
// UI: render generic success regardless, to prevent enumeration Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check address exists (admin/integration use only)
identities, err := adminClient.ListIdentities(ctx,
admin.IdentityListWithCredentialsIdentifier(addr))
if err != nil || len(identities) == 0 { /* unknown address */ } Try / catch
if herodot.ErrorStatusReason(err) == http.StatusNotFound || strings.Contains(err.Error(), "unknown address") {
// show generic message; do not reveal account existence
} Prevention
- Always render a generic confirmation after recovery/verification submission regardless of this error
- Verify addresses against existing identities in admin flows before triggering sends
- Inform users that only verified/registered emails can receive recovery messages
When it happens
Trigger: Submitting a recovery/verification form (link or code strategy) with an email/address that matches no identity; recoveryV2HandleStateConfirmingAddress or recoveryHandleFormSubmission resolving no identity for the address; code sender failing its identity lookup (code_sender.go:260).
Common situations: Users mistyping their email on the recovery page; requesting recovery for an account that was deleted or never registered; tests/integrations probing with fabricated addresses.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- no credentials found
- api_key auth strategy requires a string name
- api_key auth strategy requires a string value
- basic_auth auth strategy requires a string user
- basic_auth auth strategy requires a string password
AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07).
Data as JSON: /api/errors/aa62f02035c24160.
Report an issue: GitHub.
Appendix: source
Thrown at selfservice/strategy/link/sender.go:53
logrusx.Provider
config.Provider
VerificationTokenPersistenceProvider
RecoveryTokenPersistenceProvider
hydra.Provider
httpx.ClientProvider
}
SenderProvider interface {
LinkSender() *Sender
}
Sender struct {
r senderDependencies
}
)
var ErrUnknownAddress = errors.New("verification requested for unknown address")
func NewSender(r senderDependencies) *Sender {
return &Sender{r: r}
}
// SendRecoveryLink sends a recovery link to the specified address
//
// If the address does not exist in the store and dispatching invalid emails is enabled (CourierEnableInvalidDispatch is
// true), an email is still being sent to prevent account enumeration attacks. In that case, this function returns the
// ErrUnknownAddress error.
func (s *Sender) SendRecoveryLink(ctx context.Context, f *recovery.Flow, via, to string) error {
s.r.Logger().
WithField("via", via).
WithSensitiveField("address", to).
Debug("Preparing recovery link.")
address, err := s.r.IdentityPool().FindRecoveryAddressByValue(ctx, via, to)
if errors.Is(err, sqlcon.ErrNoRows()) {View on GitHub (pinned to b86338da04)