{"record":{"id":"4d9f5a84161da3a2","repo":"bitwarden/server","slug":"unable-to-delete-webauthn-credential","errorCode":null,"errorMessage":"Unable to delete WebAuthn credential.","messagePattern":"Unable to delete WebAuthn credential\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/Auth/Controllers/TwoFactorController.cs","lineNumber":382,"sourceCode":"        return new TwoFactorWebAuthnUpdateResponseModel(user);\n    }\n\n    [HttpPost(\"webauthn\")]\n    [Obsolete(\"This endpoint is deprecated. Use PUT /webauthn instead.\")]\n    public async Task<TwoFactorWebAuthnUpdateResponseModel> PostWebAuthn([FromBody] TwoFactorWebAuthnUpdateRequestModel model)\n    {\n        return await PutWebAuthn(model);\n    }\n\n    [HttpDelete(\"webauthn\")]\n    public async Task<TwoFactorWebAuthnDeleteResponseModel> DeleteWebAuthn(\n        [FromBody] TwoFactorWebAuthnDeleteRequestModel model)\n    {\n        var user = await ValidateUserVerificationTokenAsync(model.UserVerificationToken, TwoFactorProviderType.WebAuthn);\n\n        if (!model.Id.HasValue)\n        {\n            throw new BadRequestException(\"Unable to delete WebAuthn credential.\");\n        }\n\n        var success = await _deleteTwoFactorWebAuthnCredentialCommand.DeleteTwoFactorWebAuthnCredentialAsync(user, model.Id.Value);\n        if (!success)\n        {\n            throw new BadRequestException(\"Unable to delete WebAuthn credential.\");\n        }\n\n        return new TwoFactorWebAuthnDeleteResponseModel(user);\n    }\n\n    [HttpDelete(\"webauthn/all\")]\n    [ProducesResponseType(StatusCodes.Status204NoContent)]\n    public async Task<IActionResult> DeleteWebAuthnAll(\n        [FromBody] TwoFactorWebAuthnDeleteAllRequestModel model)\n    {\n        var user = await ValidateUserVerificationTokenAsync(model.UserVerificationToken, TwoFactorProviderType.WebAuthn);\n        await _userService.DisableTwoFactorProviderAsync(user, TwoFactorProviderType.WebAuthn);","sourceCodeStart":364,"sourceCodeEnd":400,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Auth/Controllers/TwoFactorController.cs#L364-L400","documentation":"BadRequestException 'Unable to delete WebAuthn credential.' is thrown in DELETE /webauthn (DeleteWebAuthn) when model.Id has no value (null/empty guid). The delete command requires a concrete credential id; without it the request is rejected before the command runs.","triggerScenarios":"DELETE /api/users/two-factor/webauthn (TwoFactorController line 382) where the request body omits Id or sends it as null. The !model.Id.HasValue guard fires.","commonSituations":"Client serializes the credential id as null, sends an empty body, or references a credential list that has no selected id. A deserialization mismatch (wrong casing) can also leave Id null.","solutions":["Include a non-empty Guid in the Id field of the delete request body.","Verify JSON property casing matches the request model (Id vs id) and that serialization is not dropping nulls.","Fetch the credential list first and pass the selected credential's Id."],"exampleFix":"// before\napi.delete('/users/two-factor/webauthn', { data: { userVerificationToken } }) // missing id\n// after\napi.delete('/users/two-factor/webauthn', { data: { userVerificationToken, id: selectedCredentialId } });","handlingStrategy":"validation","validationCode":"if (!model.id) throw new Error('A WebAuthn credential id is required to delete');","typeGuard":"function hasCredentialId(m): m is { id: string } { return !!m?.id && typeof m.id === 'string'; }","tryCatchPattern":"try { await api.delete('/users/two-factor/webauthn', { data: model }); }\ncatch (e) {\n  if (e.response?.status === 400 && /delete WebAuthn/.test(e.response.data?.message) && !model.id) {\n    throw new UserFacingError('Select a credential to delete.');\n  }\n  throw e;\n}","preventionTips":["Always include the credential Id in the delete body.","Verify JSON casing (Id/id) matches the server model.","Fetch the credential list first to obtain a valid Id."],"tags":["two-factor","webauthn","validation","delete"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}