{"record":{"id":"7070b376e3def9e6","repo":"gravitational/teleport","slug":"authclient-errnomfadevices-error","errorCode":null,"errorMessage":"authclient.ErrNoMFADevices.Error()","messagePattern":"authclient\\.ErrNoMFADevices\\.Error\\(\\)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/srv/app/connections_handler.go","lineNumber":899,"sourceCode":"\t\tc.log.ErrorContext(c.closeContext, \"Unable to extract connection from context.\")\n\t}\n\terr := c.getAndDeleteConnAuth(conn)\n\tif err == nil {\n\t\terr = c.serveHTTP(w, r)\n\t}\n\tif err != nil {\n\t\tc.log.WarnContext(c.closeContext, \"Failed to serve request\", \"error\", err)\n\n\t\t// Convert trace error type to HTTP and write response, make sure we close the\n\t\t// connection afterwards so that the monitor is recreated if needed.\n\t\tcode := trace.ErrorToCode(err)\n\t\tw.Header().Set(\"Connection\", \"close\")\n\n\t\tswitch {\n\t\tcase errors.Is(err, services.ErrTrustedDeviceRequired):\n\t\t\twriteTrustedDeviceRequired(w, r, code)\n\t\tcase errors.Is(err, services.ErrSessionMFARequired):\n\t\t\thttp.Error(w, authclient.ErrNoMFADevices.Error(), code)\n\t\tdefault:\n\t\t\thttp.Error(w, http.StatusText(code), code)\n\t\t}\n\t}\n}\n\nconst (\n\ttrustedDeviceRequiredDocsURL          = \"https://goteleport.com/docs/zero-trust-access/device-trust/device-management/#troubleshooting\"\n\ttrustedDeviceRequiredWebUIDocsURL     = \"https://goteleport.com/docs/zero-trust-access/device-trust/device-management/#web-ui-fails-to-authenticate-trusted-device\"\n\ttrustedDeviceRequiredAppAccessDocsURL = \"https://goteleport.com/docs/zero-trust-access/device-trust/device-management/#app-access-and-access-to-this-app-requires-a-trusted-device\"\n)\n\n// writeTrustedDeviceRequired writes the response body for a request that failed\n// with [services.ErrTrustedDeviceRequired]. Browsers receive a small HTML page\n// with clickable links to the docs; every other client gets plain text.\nfunc writeTrustedDeviceRequired(w http.ResponseWriter, r *http.Request, code int) {\n\tif isBrowserUserAgent(r.UserAgent()) {\n\t\tconst body = `<!DOCTYPE html>","sourceCodeStart":881,"sourceCodeEnd":917,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/lib/srv/app/connections_handler.go#L881-L917","documentation":"In the app connections handler's ServeHTTP error path, when the error is authclient.ErrNoMFADevices the response body is that sentinel's message ('no MFA devices found'), telling the user their per-session-MFA-gated app request failed because they have no MFA devices registered.","triggerScenarios":"Thrown at lib/srv/app/connections_handler.go:899 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Register an MFA device: tsh mfa add","Use a cluster/auth preference that does not require per-session MFA for this app, if appropriate"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}