gravitational/teleport · error

: status

Error message

%v: status %d

What it means

errorFromStatus on macOS wraps a failure into a Go error. When no human-readable message is available, it falls back to formatting the raw numeric status code: "<prefix>: status <N>". The numeric code comes from the underlying framework call (e.g. errSec codes or LAError codes), so it must be decoded to understand the failure.

Solutions

  1. Map the numeric status to its OSStatus/errSec meaning (e.g. errSecItemNotFound = -25300) to identify the cause.
  2. If the status indicates the credential/key is missing, re-register the credential with Register.
  3. Check device capabilities (IsAvailable/Touch ID enrollment) before calling to avoid unsupported-environment statuses.
  4. Improve diagnostics by passing the localized description from the underlying NSError into errorFromStatus's msg parameter.

Example fix

// before
return errorFromStatus("key generation", int(res), "") // loses detail
// after
return errorFromStatus("key generation", int(res), localizedDescription(for: res))
Defensive patterns

Strategy: fallback

Validate before calling

if !IsAvailable() {
    return errors.New("touchid unavailable; use password or hardware-key flow")
}

Type guard

func isStatusError(err error) bool {
    var target *statusError
    return errors.As(err, &target)
}
// or by message shape:
func hasRawStatus(err error) bool {
    return err != nil && strings.Contains(err.Error(), "status ")
}

Try / catch

err := api.ListCredentials()
if err != nil {
    if strings.Contains(err.Error(), "status -25300") { // errSecItemNotFound
        return nil // nothing registered yet — not a failure
    }
    if strings.Contains(err.Error(), "status ") {
        return trace.Wrap(err, "touchid failed with raw OSStatus; map the code to its errSec meaning")
    }
    return trace.Wrap(err)
}

Prevention

When it happens

Trigger: Any Touch ID operation (Guard, Register, Authenticate, FindCredentials, ListCredentials, DeleteCredential) returning a non-zero status with an empty message string, e.g. a raw OSStatus from Security framework calls that lack a localized description.

Common situations: Low-level keychain errors (e.g. status -25291 unavailable, -25300 item not found); DeviceCheck/Secure Enclave calls failing without a message; running in environments where biometrics APIs return bare status codes (CI, headless context, no T2/Apple silicon).

Related errors


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

Appendix: source

Thrown at lib/auth/touchid/api_darwin.go:439

func (touchIDImpl) DeleteNonInteractive(credentialID string) error {
	idC := C.CString(credentialID)
	defer C.free(unsafe.Pointer(idC))

	switch res := C.DeleteNonInteractive(idC); res {
	case 0: // aka success
		return nil
	case errSecItemNotFound:
		return ErrCredentialNotFound
	default:
		return errorFromStatus("non-interactive delete", int(res), "" /* msg */)
	}
}

func errorFromStatus(prefix string, status int, msg string) error {
	if msg != "" {
		return fmt.Errorf("%v: %v", prefix, msg)
	}
	return fmt.Errorf("%v: status %d", prefix, status)
}

View on GitHub (pinned to 1283425b60)