gravitational/teleport · error
A trusted device is required to access this resource but thi
Error message
A trusted device is required to access this resource but this device has not been registered as a trusted device; use 'tsh device enroll' to register as a trusted device. See https://goteleport.com/docs/zero-trust-access/device-trust/device-management/#troubleshooting for help.
What it means
Error "A trusted device is required to access this resource but this device has not been registered as a trusted device; use 'tsh device enroll' to register as a trusted device. See https://goteleport.com/docs/zero-trust-access/device-trust/device-management/#troubleshooting for help. " thrown in gravitational/teleport.
Source
Thrown at lib/srv/app/connections_handler.go:933
func writeTrustedDeviceRequired(w http.ResponseWriter, r *http.Request, code int) {
if isBrowserUserAgent(r.UserAgent()) {
const body = `<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><title>Trusted device required</title></head>
<body>
<p>A trusted device is required to access this resource, but this session has not been authorized with Device Trust. Follow <a href="` + trustedDeviceRequiredWebUIDocsURL + `" target="_blank">the Web UI troubleshooting guide</a> to authorize the session with Device Trust.</p>
<p>If accessing the resource through VNet or a local proxy, make sure the device running Teleport Connect or tsh is registered and enrolled. See <a href="` + trustedDeviceRequiredAppAccessDocsURL + `" target="_blank">the app access troubleshooting guide</a> for help.</p>
</body>
</html>
`
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.WriteHeader(code)
_, _ = w.Write([]byte(body))
return
}
http.Error(w, `A trusted device is required to access this resource but this device has not been registered as a trusted device; use 'tsh device enroll' to register as a trusted device.
See `+trustedDeviceRequiredDocsURL+` for help.
`, code)
}
// isBrowserUserAgent reports whether ua plausibly comes from a web browser, as
// opposed to a CLI (tsh, curl) or some SDK client. It relies on the historical
// quirk that essentially every browser UA begins with "Mozilla/" and contains
// a known engine token. Modern browsers (Chrome, Safari, Edge, Opera, mobile
// browsers) are all WebKit- or Blink-based and carry "AppleWebKit"; the Firefox
// family carries "Gecko/".
func isBrowserUserAgent(ua string) bool {
lower := strings.ToLower(ua)
return strings.HasPrefix(lower, "mozilla/") &&
(strings.Contains(lower, "applewebkit") || strings.Contains(lower, "gecko/"))
}
// getConnectionInfo extracts identity information from the providedView on GitHub (pinned to 1283425b60)
Solutions
- Enroll the device: run 'tsh device enroll' with an enrollment token from an administrator
- If accessing via VNet or a local proxy, ensure it is launched from the enrolled device and the device certificate is present
- See the Device Trust troubleshooting docs linked in the error message
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at lib/srv/app/connections_handler.go:933 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02).
Data as JSON: /api/errors/8cf88d12122dd439.
Report an issue: GitHub.