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

  1. Log the full result.error string and check the backend log — change_binding warn!-logs the reason right before returning Err
  2. Guard in the UI: refuse to call changeBinding with an empty or whitespace-only binding string
  3. If the backend signature changed, regenerate tauri-specta bindings (bindings.ts) and rebuild
  4. 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

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


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