tinyhumansai/openhuman · warning

worktreeApi.status: path is required

Error message

worktreeApi.status: path is required

What it means

A client-side precondition guard in worktreeApi.status(): it trims the path argument and throws before any RPC when empty. 'openhuman.worktree_status' addresses one checkout by path; an empty path is always a caller bug (no worktree selected), so the guard fails fast with a descriptive message.

Source

Thrown at app/src/services/api/worktreeApi.ts:62

  worktrees: WorktreeStatus[];
  overlaps: WorktreeOverlap[];
}

export const worktreeApi = {
  /** List managed worker worktrees plus cross-worktree file overlaps. */
  list: async (): Promise<WorktreeListView> => {
    log('list');
    const view = await callCoreRpc<WorktreeListView>({
      method: 'openhuman.worktree_list',
      params: {},
    });
    log('list received count=%d overlaps=%d', view.worktrees.length, view.overlaps.length);
    return view;
  },

  /** Fetch the branch / dirty / changed-files snapshot for one worktree. */
  status: async (path: string): Promise<WorktreeStatus> => {
    if (!path.trim()) throw new Error('worktreeApi.status: path is required');
    log('status path=%s', path);
    return callCoreRpc<WorktreeStatus>({ method: 'openhuman.worktree_status', params: { path } });
  },

  /** Fetch a human-readable `git diff HEAD --stat` (plus untracked files). */
  diff: async (path: string): Promise<string> => {
    if (!path.trim()) throw new Error('worktreeApi.diff: path is required');
    log('diff path=%s', path);
    const res = await callCoreRpc<{ summary: string }>({
      method: 'openhuman.worktree_diff',
      params: { path },
    });
    return res.summary;
  },

  /**
   * Remove a worktree checkout. The core refuses a dirty worktree unless
   * `force` is `true`, so a clean worktree removes silently while a dirty one

View on GitHub (pinned to a221052e0d)

Solutions

  1. Gate the action on selection: only call status() when a non-empty path is selected
  2. Disable the detail view / show an empty state while selectedPath is blank
  3. Guard effects: if (!path.trim()) return; as the first line of any effect that calls this
  4. Check the component's state wiring if it fires with '' — the selection binding is the bug

Example fix

// before
useEffect(() => { worktreeApi.status(path); }, [path]);

// after
useEffect(() => {
  if (!path.trim()) return;
  worktreeApi.status(path);
}, [path]);
Defensive patterns

Strategy: validation

Validate before calling

if (!path?.trim()) {
  setSelectedWorktree(null); // nothing selected — do not call status()
  return;
}
await worktreeApi.status(path);

Prevention

When it happens

Trigger: A worktree detail panel or keyboard shortcut firing before a worktree is selected; a selectedWorktree state that is '' on first render; a list-to-detail data flow passing an unpopulated binding.

Common situations: UI race where the detail view mounts before selection propagates; effects that run on mount with default empty state; refactors that renamed the path field leaving the binding empty.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16). Data as JSON: /api/errors/befa8a7b135f92ba. Report an issue: GitHub.