{"record":{"id":"aa62f02035c24160","repo":"ory/kratos","slug":"verification-requested-for-unknown-address","errorCode":null,"errorMessage":"verification requested for unknown address","messagePattern":"verification requested for unknown address","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"selfservice/strategy/link/sender.go","lineNumber":53,"sourceCode":"\t\tlogrusx.Provider\n\t\tconfig.Provider\n\n\t\tVerificationTokenPersistenceProvider\n\t\tRecoveryTokenPersistenceProvider\n\n\t\thydra.Provider\n\t\thttpx.ClientProvider\n\t}\n\tSenderProvider interface {\n\t\tLinkSender() *Sender\n\t}\n\n\tSender struct {\n\t\tr senderDependencies\n\t}\n)\n\nvar ErrUnknownAddress = errors.New(\"verification requested for unknown address\")\n\nfunc NewSender(r senderDependencies) *Sender {\n\treturn &Sender{r: r}\n}\n\n// SendRecoveryLink sends a recovery link to the specified address\n//\n// If the address does not exist in the store and dispatching invalid emails is enabled (CourierEnableInvalidDispatch is\n// true), an email is still being sent to prevent account enumeration attacks. In that case, this function returns the\n// ErrUnknownAddress error.\nfunc (s *Sender) SendRecoveryLink(ctx context.Context, f *recovery.Flow, via, to string) error {\n\ts.r.Logger().\n\t\tWithField(\"via\", via).\n\t\tWithSensitiveField(\"address\", to).\n\t\tDebug(\"Preparing recovery link.\")\n\n\taddress, err := s.r.IdentityPool().FindRecoveryAddressByValue(ctx, via, to)\n\tif errors.Is(err, sqlcon.ErrNoRows()) {","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/selfservice/strategy/link/sender.go#L35-L71","documentation":"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).","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nPOST /self-service/recovery  {\"email\": \"typo@exmaple.com\"}\n// after\nPOST /self-service/recovery  {\"email\": \"user@example.com\"}  // address must match a known identity\n// UI: render generic success regardless, to prevent enumeration","handlingStrategy":"try-catch","validationCode":"// pre-check address exists (admin/integration use only)\nidentities, err := adminClient.ListIdentities(ctx,\n  admin.IdentityListWithCredentialsIdentifier(addr))\nif err != nil || len(identities) == 0 { /* unknown address */ }","typeGuard":null,"tryCatchPattern":"if herodot.ErrorStatusReason(err) == http.StatusNotFound || strings.Contains(err.Error(), \"unknown address\") {\n  // show generic message; do not reveal account existence\n}","preventionTips":["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"],"tags":["recovery","verification","auth","ory"],"backgroundTag":"resource-not-found","analyzedSha":"b86338da04a040247a07f46100a86dcfb3875909","analyzedAt":"2026-09-07T15:58:15.934Z","contentChangedAt":"2026-09-07T15:58:15.934Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}