{"record":{"id":"fc9e31dfc704d04d","repo":"gravitational/teleport","slug":"webauthn-error-code-v","errorCode":null,"errorMessage":"webauthn error code %v","messagePattern":"webauthn error code (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"lib/auth/webauthnwin/webauthn_windows.go","lineNumber":224,"sourceCode":"\t\t\t},\n\t\t\tRawID: credential,\n\t\t},\n\t\tAttestationResponse: wantypes.AuthenticatorAttestationResponse{\n\t\t\tAuthenticatorResponse: wantypes.AuthenticatorResponse{\n\t\t\t\tClientDataJSON: in.jsonEncodedClientData,\n\t\t\t},\n\t\t\tAttestationObject: bytesFromCBytes(out.cbAttestationObject, out.pbAttestationObject),\n\t\t},\n\t}, nil\n}\n\nfunc getErrorNameOrLastErr(in uintptr, lastError error) error {\n\tret := webAuthNGetErrorName(in)\n\tif ret == 0 {\n\t\tif lastError != syscall.Errno(0) {\n\t\t\treturn fmt.Errorf(\"webauthn error code %v and syscall err: %v\", in, lastError)\n\t\t}\n\t\treturn fmt.Errorf(\"webauthn error code %v\", in)\n\t}\n\terrString := windows.UTF16PtrToString((*uint16)(unsafe.Pointer(ret)))\n\treturn fmt.Errorf(\"webauthn error code %v: %v\", in, errString)\n}\n\nfunc isUVPlatformAuthenticatorAvailable() (bool, error) {\n\tvar out bool\n\tret, err := webAuthNIsUserVerifyingPlatformAuthenticatorAvailable(&out)\n\tif err != nil {\n\t\treturn false, getErrorNameOrLastErr(ret, err)\n\t}\n\treturn out, nil\n}\n\n// bytesFromCBytes gets slice of bytes from C type and copies it to new slice\n// so that it won't interfere when main objects is free.\nfunc bytesFromCBytes(size uint32, p *byte) []byte {\n\tif p == nil {","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/lib/auth/webauthnwin/webauthn_windows.go#L206-L242","documentation":"This is the bare fallback branch of getErrorNameOrLastErr in Teleport's Windows WebAuthn wrapper. It fires when a native WebAuthn call fails, webAuthNGetErrorName returns 0 (the code is unrecognized), AND the last Win32 syscall error is exactly 0 — meaning Windows set no syscall error, so the wrapper can only report the raw numeric WebAuthn error code with no name and no OS detail. It indicates the operation failed but neither the API's name table nor GetLastError explains why.","triggerScenarios":"GetAssertion, MakeCredential, or isUVPlatformAuthenticatorAvailable returning an unmapped WebAuthn result code while GetLastError() is ERROR_SUCCESS (0) — e.g. the platform authenticator reports a generic/vendor HRESULT without recording a Win32 error, or a status code (like a retry/time-out code) that the wrapper's name table simply doesn't cover.","commonSituations":"Newer or older WebAuthn.dll returning codes not present in Teleport's mapping table; vendor security keys returning proprietary status codes; Windows Hello timing out without a Win32 error; CI/VDI environments with virtualized authenticators returning unusual codes.","solutions":["Decode the numeric code in the message against Microsoft's WebAuthn HRESULT list to identify the failure.","Upgrade Teleport so the error-name table includes the newly mapped code.","Retry the WebAuthn ceremony once — some codes are transient (user presence timeouts).","If reproducible, file an issue with the numeric code so the mapping table can be extended.","Test with a different authenticator (Windows Hello vs USB security key) to isolate the device."],"exampleFix":"// before\nerr := getErrorNameOrLastErr(code, lastErr) // \"webauthn error code 536870943\" — no context\n\n// after: give callers a typed, decodable error\nif lastError != syscall.Errno(0) {\n    return fmt.Errorf(\"webauthn error code %v and syscall err: %v\", in, lastError)\n}\nreturn fmt.Errorf(\"webauthn error code %v (0x%08X): unknown WebAuthn status; see Microsoft WebAuthn HRESULT docs\", in, uint32(in))","handlingStrategy":"retry","validationCode":"// Pre-flight: only attempt the ceremony when the platform authenticator answers cleanly\navailable, err := isUVPlatformAuthenticatorAvailable()\nif err != nil {\n    return trace.Wrap(err)\n}\nif !available {\n    return trace.BadParameter(\"WebAuthn unavailable: connect a security key or enable Windows Hello\")\n}","typeGuard":"// Detect the bare-code form: contains a code but no syscall errno\nfunc isBareWebauthnCodeErr(err error) bool {\n    if err == nil {\n        return false\n    }\n    msg := err.Error()\n    return strings.HasPrefix(msg, \"webauthn error code \") && !strings.Contains(msg, \"syscall err\")\n}","tryCatchPattern":"resp, err := MakeCredential(ctx, req)\nif err != nil {\n    if isBareWebauthnCodeErr(err) {\n        // unrecognized code with no OS detail — usually transient; retry once\n        if resp, err = MakeCredential(ctx, req); err != nil {\n            return trace.Wrap(err, \"webauthn failed with unmapped code %v; report this code\", err)\n        }\n    }\n    return trace.Wrap(err)\n}","preventionTips":["Retry once on bare unmapped codes before failing — many are transient timeouts","Keep Teleport current so newly published WebAuthn HRESULTs get name mappings","Record the numeric code in telemetry to correlate with specific devices/OS builds","Test ceremonies on both Windows Hello and hardware keys to catch device-specific codes early"],"tags":["windows","webauthn","syscall","mfa","diagnostics"],"backgroundTag":"webauthn-error-code","analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}