gitbutlerapp/gitbutler · error

Could not find selected project

Error message

Could not find selected project

What it means

useRevealInFolder returns a callback that reads the projects list directly from the query cache via queryClient.getQueryData and looks up projectId. If the cache holds no such project (or no data at all), the project's path can't be resolved and the callback throws instead of revealing a nonexistent location in the file manager.

Solutions

  1. Ensure the listProjects query has been fetched (or prefetch it) before enabling the reveal action.
  2. Check that the projectId passed to useRevealInFolder matches a project in the cached list.
  3. Handle the throw at the call site with a user-facing message instead of an unhandled rejection.
  4. Use a useQuery hook (not raw getQueryData) so loading state is known before the action is available.

Example fix

// before
const projects = queryClient.getQueryData(listProjectsQueryOptions.queryKey);
const projectPath = projects?.find((project) => project.id === projectId)?.path;
if (projectPath === undefined) throw new Error("Could not find selected project");

// after
const { data: projects } = useQuery(listProjectsQueryOptions);
const projectPath = projects?.find((project) => project.id === projectId)?.path;
const reveal = useCallback(async (path: string) => {
  if (!projectPath) return; // silently no-op when project is unavailable
  const absolutePath = await window.lite.pathJoin(projectPath, path);
  await window.lite.showItemInFolder(absolutePath);
}, [projectPath]);
Defensive patterns

Strategy: fallback

Validate before calling

const projects = queryClient.getQueryData<Project[]>(listProjectsQueryOptions.queryKey);
const projectPath = projects?.find((p) => p.id === projectId)?.path;
if (projectPath === undefined) return; // skip action before invoking

Type guard

const resolveProjectPath = (projects: unknown, id: string): string | undefined =>
  Array.isArray(projects)
    ? (projects as { id: string; path?: string }[]).find((p) => p.id === id)?.path
    : undefined;

Try / catch

try {
  await reveal(path);
} catch (e) {
  if (e instanceof Error && e.message === "Could not find selected project") {
    toast.error("Project is no longer available");
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the returned reveal(path) function when the listProjects query data is absent from the cache or contains no project with the given id — e.g. cache evicted, query never fetched, project deleted, or a wrong projectId passed in.

Common situations: Clicking 'Reveal in folder' right after app start before projects are fetched; project was deleted in another instance; projectId mismatch after a route/data refactor; getQueryData returning undefined because the observer wasn't mounted anywhere.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/c19c2a8fd723cc1e. Report an issue: GitHub.

Appendix: source

Thrown at apps/lite/ui/src/routes/project/$id/workspace/useRevealInFolder.ts:18

import { listProjectsQueryOptions } from "#ui/api/queries.ts";
import { useQueryClient } from "@tanstack/react-query";

/**
 * Reveals a repository-relative path in the OS file manager. Only the
 * project's location turns that path absolute, so it is resolved here rather
 * than at each of the surfaces — file rows, hunks, the diff — that offer the
 * action. The list is read when the action runs rather than subscribed to:
 * nothing here renders it, and a surface that suspended on it would tear down
 * the very rows it lists.
 */
export const useRevealInFolder = (projectId: string): ((path: string) => Promise<void>) => {
	const queryClient = useQueryClient();

	return async (path) => {
		const projects = queryClient.getQueryData(listProjectsQueryOptions.queryKey);
		const projectPath = projects?.find((project) => project.id === projectId)?.path;
		if (projectPath === undefined) throw new Error("Could not find selected project");

		const absolutePath = await window.lite.pathJoin(projectPath, path);
		await window.lite.showItemInFolder(absolutePath);
	};
};

View on GitHub (pinned to 58e5313667)