gravitational/teleport · error
unexpected nil response from GetAssertion
Error message
unexpected nil response from GetAssertion
What it means
GetAssertion calls the Windows webauthn.dll entry point WebAuthNAuthenticatorGetAssertion, which reports success (ret == 0) but left the out *webauthnAssertion pointer nil. The Go wrapper treats this as an invariant violation: the Win32 API promised a result but produced none, so there is no assertion to parse and the call aborts with this plain error instead of dereferencing nil.
Source
Thrown at lib/auth/webauthnwin/webauthn_windows.go:141
)
if n.webauthnAPIVersion < int(in.opts.dwVersion) {
const legacyVersion = 5
in.opts.dwVersion = legacyVersion
logger.DebugContext(context.Background(),
"WebAuthn.dll too old, falling back to legacy version",
"api_version", n.webauthnAPIVersion,
"legacy_version", in.opts.dwVersion,
)
}
var out *webauthnAssertion
ret, err := webAuthNAuthenticatorGetAssertion(hwnd, in.rpID, in.clientData, in.opts, &out)
if ret != 0 {
return nil, trace.Wrap(getErrorNameOrLastErr(ret, err))
}
if out == nil {
return nil, errors.New("unexpected nil response from GetAssertion")
}
// Note that we need to copy bytes out of `out` if we want to free object.
// That's why bytesFromCBytes is used.
defer freeAssertion(out)
authData := bytesFromCBytes(out.cbAuthenticatorData, out.pbAuthenticatorData)
signature := bytesFromCBytes(out.cbSignature, out.pbSignature)
userID := bytesFromCBytes(out.cbUserID, out.pbUserID)
credential := bytesFromCBytes(out.Credential.cbID, out.Credential.pbID)
credType := windows.UTF16PtrToString(out.Credential.pwszCredentialType)
return &wantypes.CredentialAssertionResponse{
PublicKeyCredential: wantypes.PublicKeyCredential{
RawID: credential,
Credential: wantypes.Credential{
ID: base64.RawURLEncoding.EncodeToString(credential),
Type: credType,View on GitHub (pinned to 1283425b60)
Solutions
- Retry the WebAuthn ceremony once — transient Hello/TPM issues can clear the condition.
- Update Windows (webauthn.dll fixes ship in cumulative updates) and verify Windows Hello is set up and working in Settings > Accounts > Sign-in options.
- Fall back to another authenticator (hardware security key or non-native WebAuthn path) instead of the Windows-native implementation.
- Report to Teleport if reproducible on a supported Windows version; the code path expects a non-nil assertion on success.
Defensive patterns
Strategy: fallback
Validate before calling
// Before starting the ceremony, verify the native WebAuthn stack is usable:
if !native.HasCompileSupport() || !native.IsAvailable() {
// fall back to non-native authenticator path
} Type guard
func assertionAvailable(out *webauthnAssertion) bool { return out != nil } Try / catch
resp, err := native.GetAssertion(origin, req)
if err != nil {
if strings.Contains(err.Error(), "unexpected nil response") {
// fall back to hardware key / retry once
}
return trace.Wrap(err)
} Prevention
- Keep Windows fully updated so webauthn.dll is current.
- Verify Windows Hello is enrolled before passwordless ceremonies.
- Fall back to hardware security keys on virtualized/unsupported Windows installs.
When it happens
Trigger: Calling nativeImpl.GetAssertion (used during WebAuthn login/ceremony in tsh and Teleport on Windows) when WebAuthNAuthenticatorGetAssertion returns HR_SUCCESS (0) but does not populate the WEBAUTHN_ASSERTION output struct — a defective or partially functional webauthn.dll / Windows Hello stack.
Common situations: Older or corrupted Windows builds with a buggy webauthn.dll; Windows Hello or the platform authenticator in a broken state (TPM faults, stale credentials); running on non-standard Windows editions or virtualized environments where the API succeeds spuriously.
Related errors
- unexpected nil response from MakeCredential
- webauthn error code %v and syscall err: %v
- webauthn error code %v
- PIV is unavailable in current build
- credential not found
AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02).
Data as JSON: /api/errors/eafe7dfe0606b155.
Report an issue: GitHub.