{"record":{"id":"10423f02b4be9450","repo":"dotnet/aspnetcore","slug":"unknown-passkey-operation-this-attrs-operation","errorCode":null,"errorMessage":"Unknown passkey operation '${this.attrs.operation}'.","messagePattern":"Unknown passkey operation '(.+?)'\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWebCSharp.1/Components/Account/Shared/PasskeySubmit.razor.js","lineNumber":77,"sourceCode":"    }\n\n    disconnectedCallback() {\n        this.abortController?.abort();\n    }\n\n    async obtainCredential(useConditionalMediation, signal) {\n        if (!browserSupportsPasskeys) {\n            throw new Error('Some passkey features are missing. Please update your browser.');\n        }\n\n        if (this.attrs.operation === 'Create') {\n            return await createCredential(signal);\n        } else if (this.attrs.operation === 'Request') {\n            const email = new FormData(this.internals.form).get(this.attrs.emailName);\n            const mediation = useConditionalMediation ? 'conditional' : undefined;\n            return await requestCredential(email, mediation, signal);\n        } else {\n            throw new Error(`Unknown passkey operation '${this.attrs.operation}'.`);\n        }\n    }\n\n    async obtainAndSubmitCredential(useConditionalMediation = false) {\n        this.abortController?.abort();\n        this.abortController = new AbortController();\n        const signal = this.abortController.signal;\n        const formData = new FormData();\n        try {\n            const credential = await this.obtainCredential(useConditionalMediation, signal);\n            const credentialJson = JSON.stringify(credential);\n            formData.append(`${this.attrs.name}.CredentialJson`, credentialJson);\n        } catch (error) {\n            if (error.name === 'AbortError') {\n                // The user explicitly canceled the operation - return without error.\n                return;\n            }\n            console.error(error);","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorWeb-CSharp/BlazorWebCSharp.1/Components/Account/Shared/PasskeySubmit.razor.js#L59-L95","documentation":"Thrown by obtainCredential when this.attrs.operation is neither 'Create' nor 'Request'. The component is parameterized by an operation attribute set from the Razor host; an unrecognized value indicates a configuration or integration bug — not a runtime user error.","triggerScenarios":"The PasskeySubmit razor component passes an operation value that is not exactly 'Create' or 'Request' (case-sensitive). This happens if the attribute is left unset (undefined), mis-cased ('create'), or set to a new operation that the JS does not yet handle.","commonSituations":"Customizing the Blazor account components and renaming the operation enum; upgrading the template where a new operation was added server-side but the JS file was not updated; copy-paste of the component without wiring the operation attribute.","solutions":["Inspect the rendered PasskeySubmit element's data attributes to see the actual operation value being passed.","Ensure the Razor component sets operation to exactly 'Create' or 'Request' (case-sensitive).","If you extended the protocol with a new operation, update the if/else chain in obtainCredential to handle it before the throw.","Add a type-guard or assertion at component initialization so misconfiguration surfaces at render, not on submit."],"exampleFix":"// before\n} else {\n  throw new Error(`Unknown passkey operation '${this.attrs.operation}'.`);\n}\n\n// after — fail fast at init with an allowlist\nconst ALLOWED_OPS = new Set(['Create', 'Request']);\nif (!ALLOWED_OPS.has(this.attrs.operation)) {\n  throw new Error(`Invalid operation '${this.attrs.operation}'. Expected one of: ${[...ALLOWED_OPS].join(', ')}`);\n}","handlingStrategy":"validation","validationCode":"const PASSKEY_OPERATIONS = new Set(['Create', 'Request']);\nfunction isValidOperation(op: unknown): op is 'Create' | 'Request' {\n  return typeof op === 'string' && PASSKEY_OPERATIONS.has(op);\n}\n// assert at component attach:\nif (!isValidOperation(this.attrs.operation)) {\n  throw new TypeError(`operation must be 'Create' or 'Request', got ${this.attrs.operation}`);\n}","typeGuard":"function isPasskeyOperation(v: unknown): v is 'Create' | 'Request' {\n  return v === 'Create' || v === 'Request';\n}","tryCatchPattern":"try {\n  await obtainCredential(...);\n} catch (e) {\n  if (/Unknown passkey operation/.test(e.message)) {\n    console.error('Component misconfigured — operation attr:', this.attrs.operation);\n  } else throw e;\n}","preventionTips":["Validate operation at component initialization, not on submit.","Treat operation as a closed enum shared between Razor and JS.","Add a unit test asserting the attribute matches the JS allowlist."],"tags":["configuration","passkey","validation","blazor","programming-error"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}