gravitational/teleport · warning

touch ID not available

Error message

touch ID not available

What it means

ErrNotAvailable is the sentinel error of the touchid package, indicating the platform authenticator (Touch ID) is not usable on the current machine. Every public entry point (Register, Login, ListCredentials, DeleteCredential, Guard, Authenticate) checks IsAvailable() first and returns this error when the check fails. It lets callers degrade gracefully to other MFA methods instead of failing unpredictably deeper in the stack.

Source

Thrown at lib/auth/touchid/api.go:52

	"sort"
	"sync"
	"sync/atomic"
	"time"

	"github.com/fxamacker/cbor/v2"
	"github.com/go-webauthn/webauthn/protocol"
	"github.com/go-webauthn/webauthn/protocol/webauthncose"
	"github.com/gravitational/trace"

	"github.com/gravitational/teleport"
	wantypes "github.com/gravitational/teleport/lib/auth/webauthntypes"
	"github.com/gravitational/teleport/lib/darwin"
	logutils "github.com/gravitational/teleport/lib/utils/log"
)

var (
	ErrCredentialNotFound = errors.New("credential not found")
	ErrNotAvailable       = errors.New("touch ID not available")

	// PromptPlatformMessage is the message shown before Touch ID prompts.
	PromptPlatformMessage = "Using platform authenticator, follow the OS prompt"
	// PromptWriter is the writer used for prompt messages.
	PromptWriter io.Writer = os.Stderr

	logger = logutils.NewPackageLogger(teleport.ComponentKey, "TouchID")
)

func promptPlatform() {
	if PromptPlatformMessage != "" {
		fmt.Fprintln(PromptWriter, PromptPlatformMessage)
	}
}

// AuthContext is an optional, shared authentication context.
// Allows reusing a single authentication prompt/gesture between different
// functions, provided the functions are invoked in a short time interval.

View on GitHub (pinned to 1283425b60)

Solutions

  1. Check touchid.IsAvailable() before calling any touchid API and fall back to another authenticator (e.g. webauthncli/FIDO2) when false.
  2. Enroll fingerprints in System Settings > Touch ID & Password on macOS.
  3. Verify the app/binary is running on real macOS hardware with a Secure Enclave, not a VM or container.
  4. If MDM blocks biometrics, ask IT to allow Touch ID or use an alternate MFA device.

Example fix

// before
reg, err := touchid.Register(origin, cc)
// after
if !touchid.IsAvailable() {
	return mfaFallbackRegister(origin, cc) // e.g. FIDO2 flow
}
reg, err := touchid.Register(origin, cc)
Defensive patterns

Strategy: fallback

Validate before calling

if !touchid.IsAvailable() {
	// use FIDO2 or another MFA method instead
}

Type guard

func available() bool { return touchid.IsAvailable() }

Try / catch

reg, err := touchid.Register(origin, cc)
if errors.Is(err, touchid.ErrNotAvailable) {
	reg, err = fidoFallbackRegister(origin, cc)
}

Prevention

When it happens

Trigger: Calling any touchid API (Register at api.go:231, Login at api.go:451, ListCredentials, DeleteCredential, Guard, Authenticate) when IsAvailable() returns false: no Touch ID hardware, unsupported macOS version, or the underlying darwin/CTK API reports the authenticator unavailable.

Common situations: Running Teleport client on Linux/Windows where lib/auth/touchid is compiled but no Touch ID exists; macOS without Touch ID (desktop Macs, VMs); biometrics not enrolled or disabled by MDM/policy; Secure Enclave unavailable.

Related errors


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