{"record":{"id":"d29543d647c7ca69","repo":"ory/kratos","slug":"no-identifier-found","errorCode":null,"errorMessage":"no identifier found","messagePattern":"no identifier found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"selfservice/strategy/passkey/passkey_schema_extension.go","lineNumber":25,"sourceCode":"\t\"cmp\"\n\t\"context\"\n\t\"fmt\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/ory/jsonschema/v3\"\n\t\"github.com/ory/kratos/identity\"\n\t\"github.com/ory/kratos/schema\"\n\t\"github.com/ory/x/jsonschemax\"\n)\n\n// errNoDisplayNameTrait is returned by PasskeyDisplayNameFromSchema when the\n// identity schema flags no trait as a passkey display name or WebAuthn\n// identifier and has no untitled trait to fall back to.\nvar errNoDisplayNameTrait = errors.New(\"no identifier found\")\n\ntype SchemaExtension struct {\n\tWebauthnIdentifier string\n\tPasskeyDisplayName string\n\tsync.Mutex\n}\n\nfunc (e *SchemaExtension) Run(_ jsonschema.ValidationContext, s schema.ExtensionConfig, value any) error {\n\te.Lock()\n\tdefer e.Unlock()\n\n\t// When a schema flags multiple traits, the validator visits them in an\n\t// unspecified order. Keep the first non-empty value so an empty flagged\n\t// trait never clobbers a populated one. This mirrors the client, which\n\t// names the passkey after the first non-empty candidate field.\n\tif s.Credentials.WebAuthn.Identifier && e.WebauthnIdentifier == \"\" {\n\t\te.WebauthnIdentifier = strings.ToLower(fmt.Sprintf(\"%s\", value))\n\t}","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/selfservice/strategy/passkey/passkey_schema_extension.go#L7-L43","documentation":"errNoDisplayNameTrait signals that the identity JSON schema does not flag any trait as a passkey display name or WebAuthn identifier and offers no untitled trait to fall back to. PasskeyDisplayNameFromSchema returns it, and the passkey registration strategy uses errors.Is to skip the passkey method gracefully when it is misconfigured. It is a sentinel error, not an end-user message.","triggerScenarios":"Running passkey registration/ login when the identity schema has no trait annotated as webauthn identifier/display name and no untitled single trait exists.","commonSituations":"Custom identity schemas that omit passkey-related annotations; renaming traits so the passkey schema extension no longer finds the display name; enabling passkeys with a minimal/default schema lacking the required annotations.","solutions":["Add a title (e.g. 'email' or annotate as WebAuthn identifier) to the trait that should serve as passkey display name in the identity JSON schema","Use an identity schema with at least one untitled trait the extension can fall back to","Check skipMethodOnMissingDisplayName behavior: the flow continues with another method, so treat this as a schema misconfiguration warning"],"exampleFix":"// before (schema)\n{\"properties\": {\"email\": {\"type\": \"string\", \"format\": \"email\"}}}\n// after\n{\"properties\": {\"email\": {\"type\": \"string\", \"format\": \"email\", \"title\": \"Email\", \"ory.sh/passkey\": {\"display_name\": true}}}}","handlingStrategy":"fallback","validationCode":"// pre-check schema: jsonschemax.Paths(...) contains a trait with passkey display-name annotation","typeGuard":null,"tryCatchPattern":"if errors.Is(err, errNoDisplayNameTrait) { // fall back to another auth method / log schema misconfiguration\n    return nil\n}","preventionTips":["Annotate one trait as passkey display name in every identity schema","Keep trait titles stable when refactoring schemas","Test registration flows per schema change"],"tags":["go","passkey","webauthn","json-schema"],"backgroundTag":"missing-required-config-field","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"}