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
- Ensure the listProjects query has been fetched (or prefetch it) before enabling the reveal action.
- Check that the projectId passed to useRevealInFolder matches a project in the cached list.
- Handle the throw at the call site with a user-facing message instead of an unhandled rejection.
- 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
- Prefer useQuery hooks over raw getQueryData so loading/absence states are explicit.
- Disable the reveal action until projects data is in the cache.
- Handle async action errors with a user-visible toast instead of letting rejections go unhandled.
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
- Could not find selected project
- Could not find selected project
- Can't receive a change without it's source or commit
- Change drop data must specify the source stackId
- textFromToolResult(result)
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)