cjpais/Handy · error · Error
Failed to update binding
Error message
Failed to update binding
What it means
Frontend throw in settingsStore.updateBinding when the changeBinding Tauri command rejects (empty/whitespace binding, or shortcut fails validate_shortcut_for_implementation for the selected keyboard implementation) or returns success:false (binding id not present in settings or defaults, or the OS-level register_shortcut failed). The store then rolls back its optimistic binding update.
Source
Thrown at src/stores/settingsStore.ts:370
[id]: {
...state.settings.bindings?.[id]!,
current_binding: binding,
},
},
}
: null,
}));
const result = await commands.changeBinding(id, binding);
// Check if the command executed successfully
if (result.status === "error") {
throw new Error(result.error);
}
// Check if the binding change was successful
if (!result.data.success) {
throw new Error(result.data.error || "Failed to update binding");
}
} catch (error) {
console.error(`Failed to update binding ${id}:`, error);
// Rollback on error
if (originalBinding && get().settings) {
set((state) => ({
settings: state.settings
? {
...state.settings,
bindings: {
...state.settings.bindings,
[id]: {
...state.settings.bindings?.[id]!,
current_binding: originalBinding,
},
},
}View on GitHub (pinned to 98a4d80cce)
Solutions
- Surface result.data.error / the caught message — it names the exact backend reason
- On macOS, grant Accessibility permission (System Settings > Privacy & Security > Accessibility) and retry
- Try a different key combination to rule out an OS/app conflict
- Verify the binding id matches one defined in the backend defaults
- The store already rolled back the optimistic update — re-sync UI state from settings before retrying
Example fix
// before
const result = await commands.changeBinding(id, binding);
if (!result.data.success) throw new Error(result.data.error || 'Failed to update binding');
// after — keep the backend reason
if (result.status === 'error') throw new Error(`changeBinding rejected: ${result.error}`);
if (!result.data.success) throw new Error(result.data.error ?? `changeBinding failed for ${id}`); Defensive patterns
Strategy: try-catch
Validate before calling
// reject obviously invalid input before the round-trip
if (!binding || binding.trim().length === 0) {
throw new Error('Binding cannot be empty');
}
if (!DEFAULT_BINDING_IDS.includes(id)) {
throw new Error(`Unknown binding id: ${id}`);
}
const result = await commands.changeBinding(id, binding); Type guard
type ChangeBindingResult =
| { status: 'error'; error: string }
| { status: 'ok'; data: { success: true; binding: Binding; error: null } }
| { status: 'ok'; data: { success: false; binding: null; error: string } };
function isRejected(
r: ChangeBindingResult,
): r is Extract<ChangeBindingResult, { status: 'error' }> | Extract<ChangeBindingResult, { status: 'ok'; data: { success: false } }> {
return r.status === 'error' || r.data.success === false;
} Try / catch
try {
const result = await commands.changeBinding(id, binding);
if (isRejected(result)) {
const reason = result.status === 'error' ? result.error : result.data.error;
throw new Error(reason ?? `changeBinding failed for ${id}`);
}
} catch (error) {
// rollback (already implemented) then surface `error.message` to the UI toast
} Prevention
- Disable the save action for empty or modifier-only shortcuts client-side
- Check macOS Accessibility permission during onboarding before first binding change
- Always prefer result.data.error over the generic fallback string so users see the backend reason
When it happens
Trigger: Passing an unknown binding id (typo, removed setting) — backend returns success:false with 'Binding with id ... not found in defaults'; binding string empty or only modifiers so validation fails; register_shortcut fails at the OS layer (macOS accessibility permission missing, combo already grabbed by another app or reserved by the OS).
Common situations: macOS without Accessibility permission granted for keyboard shortcuts; hotkey conflicts with system/global shortcuts of other apps; frontend calling with an id from an older settings schema; user clearing the shortcut field.
Related errors
AI-assisted analysis of cjpais/Handy@98a4d80cce (2026-08-16).
Data as JSON: /api/errors/42e5aa26649b3ce4.
Report an issue: GitHub.