gravitational/teleport · error

webauthn error code %v and syscall err: %v

Error message

webauthn error code %v and syscall err: %v

What it means

This error comes from Teleport's Windows WebAuthn wrapper (getErrorNameOrLastErr). When a call into the native WebAuthn API (MakeCredential, GetAssertion, or the platform-authenticator availability probe) fails, the wrapper asks webAuthNGetErrorName for a human-readable name for the returned error code; if that lookup returns 0 (unrecognized code) AND the last Win32 syscall error (syscall.Errno) is non-zero, it falls back to reporting the raw code plus the syscall error. It exists so that unrecognized WebAuthn result codes still surface the underlying OS error instead of being silently swallowed.

Source

Thrown at lib/auth/webauthnwin/webauthn_windows.go:222

				ID:   base64.RawURLEncoding.EncodeToString(credential),
				Type: string(protocol.PublicKeyCredentialType),
			},
			RawID: credential,
		},
		AttestationResponse: wantypes.AuthenticatorAttestationResponse{
			AuthenticatorResponse: wantypes.AuthenticatorResponse{
				ClientDataJSON: in.jsonEncodedClientData,
			},
			AttestationObject: bytesFromCBytes(out.cbAttestationObject, out.pbAttestationObject),
		},
	}, nil
}

func getErrorNameOrLastErr(in uintptr, lastError error) error {
	ret := webAuthNGetErrorName(in)
	if ret == 0 {
		if lastError != syscall.Errno(0) {
			return fmt.Errorf("webauthn error code %v and syscall err: %v", in, lastError)
		}
		return fmt.Errorf("webauthn error code %v", in)
	}
	errString := windows.UTF16PtrToString((*uint16)(unsafe.Pointer(ret)))
	return fmt.Errorf("webauthn error code %v: %v", in, errString)
}

func isUVPlatformAuthenticatorAvailable() (bool, error) {
	var out bool
	ret, err := webAuthNIsUserVerifyingPlatformAuthenticatorAvailable(&out)
	if err != nil {
		return false, getErrorNameOrLastErr(ret, err)
	}
	return out, nil
}

// bytesFromCBytes gets slice of bytes from C type and copies it to new slice
// so that it won't interfere when main objects is free.

View on GitHub (pinned to 1283425b60)

Solutions

  1. Inspect the syscall err portion of the message (e.g. 'The device is not connected', ERROR_NOT_FOUND) and fix that underlying Windows condition first.
  2. Update Teleport to a newer release so the WebAuthn error-code table covers the unmapped HRESULT.
  3. Verify Windows Hello / security key state in Windows Settings > Accounts > Sign-in options and re-run the ceremony.
  4. Collect the exact numeric code from the message and check it against Microsoft's WebAuthn HRESULT documentation.
  5. Reproduce with a standard browser WebAuthn test to confirm it is not Teleport-specific.

Example fix

// before (opaque failure at call site)
assertion, err := GetAssertion(...)
if err != nil { return err } // "webauthn error code -2147024894 and syscall err: The system cannot find the file specified."

// after (unwrap and branch on the syscall errno)
assertion, err := GetAssertion(...)
if err != nil {
    var errno syscall.Errno
    if errors.As(err, &errno) && errno == syscall.ERROR_NOT_FOUND {
        return trace.Wrap(err, "no authenticator device found; connect a security key or enable Windows Hello")
    }
    return trace.Wrap(err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before invoking WebAuthn, confirm a platform authenticator is available and reachable
available, err := isUVPlatformAuthenticatorAvailable()
if err != nil {
    var errno syscall.Errno
    if errors.As(err, &errno) {
        log.Warnf("WebAuthn device check failed with errno %d; ensure a security key is connected and Windows Hello is enabled", errno)
    }
    return trace.Wrap(err)
}
if !available {
    return trace.BadParameter("no user-verifying platform authenticator available on this machine")
}

Type guard

// Narrow the wrapped error to extract the syscall errno
func webauthnErrno(err error) (syscall.Errno, bool) {
    var errno syscall.Errno
    if errors.As(err, &errno) && errno != 0 {
        return errno, true
    }
    return 0, false
}

Try / catch

assertion, err := GetAssertion(ctx, req)
if err != nil {
    if errno, ok := webauthnErrno(err); ok {
        switch errno {
        case syscall.ERROR_DEVICE_NOT_CONNECTED:
            return trace.Wrap(err, "security key disconnected; reconnect and retry")
        case syscall.ERROR_CANCELLED:
            return trace.Wrap(err, "user cancelled the WebAuthn ceremony")
        }
    }
    return trace.Wrap(err) // unmapped code: surface raw code + errno to logs
}

Prevention

When it happens

Trigger: Any WebAuthn operation (GetAssertion, MakeCredential, isUVPlatformAuthenticatorAvailable) whose returned code is not in webAuthNGetErrorName's known-name table and whose GetLastError() is non-zero — e.g. WebAuthnGetCancellation returns a failure, the authenticator device returns a vendor-specific HRESULT, or the WebAuthn API call fails before setting a documented error name.

Common situations: Running on Windows editions/SKUs where the WebAuthn API behaves unexpectedly; security-key unplugged mid-ceremony producing an unmapped HRESULT; Windows Hello or the platform authenticator being disabled mid-operation; older Windows builds whose WebAuthn.dll returns codes this wrapper doesn't map; enterprise policy blocking WebAuthn device access.

Related errors


AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02). Data as JSON: /api/errors/89452905d49237c5. Report an issue: GitHub.