cjpais/Handy · error · Error
result.error
Error message
result.error
What it means
This error is thrown after the tauri-specta generated command `commands.changeBinding(id, binding)` resolves with `{ status: "error" }`. In Tauri 2, a command whose Rust handler returns `Err(String)` (or panics) is serialized into exactly this shape, so `result.error` carries the backend's rejection string. It means the command failed at the IPC level before producing a BindingResponse — for example `change_binding` in src-tauri/src/shortcut/mod.rs returns `Err("Binding cannot be empty")` for a blank shortcut. It is distinct from error [1], where the command succeeds but the backend reports success:false.
Source
Thrown at src/stores/settingsStore.ts:384
settings: state.settings
? {
...state.settings,
bindings: {
...state.settings.bindings,
[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]: {View on GitHub (pinned to fbd4e15fa1)
Solutions
- Log the full result.error string and check the backend log — change_binding warn!-logs the reason right before returning Err
- Guard in the UI: refuse to call changeBinding with an empty or whitespace-only binding string
- If the backend signature changed, regenerate tauri-specta bindings (bindings.ts) and rebuild
- Verify the settings store file is writable and valid JSON; reset it if corrupted
Example fix
// before
const result = await commands.changeBinding(id, binding);
if (result.status === "error") {
throw new Error(result.error);
}
// after — never send an empty binding, and keep the command + id in the thrown message
if (!binding.trim()) {
throw new Error(`Refusing empty binding for ${id}`);
}
const result = await commands.changeBinding(id, binding);
if (result.status === "error") {
throw new Error(`changeBinding(${id}) command failed: ${result.error}`);
} Defensive patterns
Strategy: try-catch
Validate before calling
// before invoking, confirm the id exists in the current settings map
const bindings = get().settings?.bindings;
if (!bindings || !(id in bindings)) {
throw new Error(`Unknown binding id: ${id}`);
}
if (!binding.trim()) {
throw new Error(`Binding for ${id} cannot be empty`);
} Type guard
export function isCommandFailure(
r: Result<unknown, string>
): r is { status: "error"; error: string } {
return r.status === "error";
} Try / catch
try {
const result = await commands.changeBinding(id, binding);
if (result.status === "error") throw new Error(result.error);
if (!result.data.success) throw new Error(result.data.error ?? "Failed to update binding");
} catch (error) {
// settingsStore already rolls back the optimistic binding here — keep that
console.error(`Failed to update binding ${id}:`, error);
// surface result.error text to the UI toast, not the generic message
} Prevention
- Validate binding strings client-side (non-empty, no whitespace-only) before every changeBinding call
- Keep the optimistic-update/rollback pair (already in settingsStore.ts) so UI never desyncs from backend state
- Regenerate bindings.ts via tauri-specta whenever change_binding's signature or error strings change
When it happens
Trigger: Passing an empty or whitespace-only binding string (rejected at shortcut/mod.rs:119); the Rust handler returning Err (e.g. settings store write failure); a stale bindings.ts that sends a payload shape the backend no longer accepts; a command panic serialized as an error string.
Common situations: UI lets the user clear a shortcut field and save before validation runs; frontend/backend binding drift after editing change_binding without regenerating bindings.ts; tauri-plugin-store write failures (locked or corrupted settings file).
Related errors
- Failed to update binding
- Failed to resolve VAD path: {}
- Failed to check Windows microphone permissions:
- Failed to sync language from settings:
- Failed to sync theme from settings:
AI-assisted analysis of cjpais/Handy@fbd4e15fa1 (2026-08-17).
Data as JSON: /api/errors/a3c5c01482140220.
Report an issue: GitHub.