cjpais/Handy · warning

Failed to initialize:

Error message

Failed to initialize:

What it means

Once onboarding is done, App.tsx fires two backend commands — initializeEnigo (Enigo, the input simulator Handy uses to paste transcriptions into other apps) and initializeShortcuts (global hotkeys via rdev) — and refreshes audio device lists. This catch logs when either init command rejects. The app keeps running, but text pasting and global shortcuts are dead until something re-initializes them, which is the functional symptom to look for.

Source

Thrown at src/App.tsx:69

  useEffect(() => {
    checkOnboardingStatus();
  }, []);

  // Initialize RTL direction when language changes
  useEffect(() => {
    initializeRTL(i18n.language);
  }, [i18n.language]);

  // Initialize Enigo, shortcuts, and refresh audio devices when main app loads
  useEffect(() => {
    if (onboardingStep === "done" && !hasCompletedPostOnboardingInit.current) {
      hasCompletedPostOnboardingInit.current = true;
      Promise.all([
        commands.initializeEnigo(),
        commands.initializeShortcuts(),
      ]).catch((e) => {
        console.warn("Failed to initialize:", e);
      });
      refreshAudioDevices();
      refreshOutputDevices();
    }
  }, [onboardingStep, refreshAudioDevices, refreshOutputDevices]);

  // Handle keyboard shortcuts for debug mode toggle
  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      // Check for Ctrl+Shift+D (Windows/Linux) or Cmd+Shift+D (macOS)
      const isDebugShortcut =
        event.shiftKey &&
        event.key.toLowerCase() === "d" &&
        (event.ctrlKey || event.metaKey);

      if (isDebugShortcut) {
        event.preventDefault();
        const currentDebugMode = settings?.debug_mode ?? false;

View on GitHub (pinned to c89b7bf389)

Solutions

  1. Inspect which of the two commands failed from the logged error; they have different remedies
  2. On Linux, run inside a real desktop session and install the X11/evdev dev libraries Handy's BUILD.md calls for
  3. On macOS, re-check System Settings > Privacy > Accessibility if shortcuts specifically fail
  4. Add a retry or user-visible 'shortcuts unavailable — click to re-init' path, since currently a failed init leaves the app degraded with only a console warning

Example fix

// before
Promise.all([commands.initializeEnigo(), commands.initializeShortcuts()]).catch((e) => {
  console.warn("Failed to initialize:", e);
});

// after
Promise.all([commands.initializeEnigo(), commands.initializeShortcuts()]).catch(
  async (e) => {
    console.warn("Failed to initialize, retrying once:", e);
    await new Promise((r) => setTimeout(r, 1500));
    try {
      await Promise.all([commands.initializeEnigo(), commands.initializeShortcuts()]);
    } catch (retryErr) {
      console.error("Initialization failed after retry — paste/shortcuts disabled:", retryErr);
      toast.warn(t("errors.initFailed"));
    }
  },
);
Defensive patterns

Strategy: retry

Try / catch

try {
  await Promise.all([commands.initializeEnigo(), commands.initializeShortcuts()]);
} catch (e) {
  console.warn("Failed to initialize:", e);
  await retryOnce(1500); // then surface a UI hint if it still fails
}

Prevention

When it happens

Trigger: Enigo init failing on Linux without X11/Wayland support or missing input libraries (headless, container, minimal session); rdev's global grab failing when another instance or security tool holds it; invoking after backend teardown; macOS where the accessibility grant was revoked between onboarding and this call.

Common situations: Linux systems missing libx11/libxdo/evdev access; VMs and CI without an input subsystem; conflicts with other global-shortcut apps; Wayland sessions with restricted key grabbing.

Related errors


AI-assisted analysis of cjpais/Handy@c89b7bf389 (2026-08-17). Data as JSON: /api/errors/cdcb3ddaaad8ee49. Report an issue: GitHub.