different-ai/openwork · error

Workspace endpoint unavailable for ${selectedId}.

Error message

Workspace endpoint unavailable for ${selectedId}.

What it means

Thrown by the activateWorkspace callback wired into the route state when no client/endpoint can be resolved for the workspace being activated. endpointForWorkspace returns null for workspaces lacking a usable connection endpoint, and activation is rejected with a message naming the workspace id.

Source

Thrown at apps/app/src/react-app/shell/use-workspace-route-state.ts:454

    [endpointForWorkspace, mergeFetchedSessionsWithPending],
  );
  const reloadWorkspaceSessions = useCallback(async (workspaceId: string): Promise<void> => {
    const workspace = workspacesRef.current.find((item) => item.id === workspaceId);
    if (!workspace) return;
    loadedWorkspaceIdsRef.current.delete(workspaceId);
    await loadWorkspaceSessionsInBackground([workspace]);
  }, [loadWorkspaceSessionsInBackground]);
  const workspaceSelectionCommitRef = useRef<(workspaceId: string) => Promise<void>>(async () => undefined);
  workspaceSelectionCommitRef.current = async (workspaceId) => {
    await commitRouteWorkspaceSelection({
      workspaceId,
      desktopRuntime: isDesktopRuntime(),
      setDesktopSelected: workspaceSetSelected,
      setDesktopRuntimeActive: workspaceSetRuntimeActive,
      activateWorkspace: async (selectedId) => {
        const workspace = workspacesRef.current.find((item) => item.id === selectedId) ?? null;
        const endpoint = endpointForWorkspace(workspace);
        if (!endpoint) throw new Error(`Workspace endpoint unavailable for ${selectedId}.`);
        if (workspace?.workspaceType === "local" && serverActiveWorkspaceIdRef.current === selectedId) return;
        await endpoint.client.activateWorkspace(endpoint.workspaceId, { persist: true });
        if (workspace?.workspaceType === "local") serverActiveWorkspaceIdRef.current = selectedId;
      },
    });
  };

  const refreshRouteState = useCallback(async (options?: { supersede?: boolean }) => {
    // Dedupe: if a refresh is already running, skip this call. Fast workspace
    // switches used to fire 5-6 overlapping refreshRouteState() calls which
    // each fetched workspaces + sessions for every workspace. That workload
    // multiplied quickly on the event loop and caused the UI to freeze.
    // Callers reacting to changed connection info pass `supersede` instead of
    // resetting the in-flight guard: the running attempt goes stale (its
    // remaining writes are discarded) rather than racing the new one.
    const attempt = refreshLifecycleRef.current.begin(options);
    if (!attempt) return;
    setLoading(true);

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Refresh the workspace list (refreshRouteState) so endpoints are populated before activating.
  2. Re-establish the workspace's connection (save/validate its remote connection) if it is a remote workspace.
  3. Check endpointForWorkspace logic/data for the missing workspace and correct stale entries.
  4. Retry activation after app/server startup completes.

Example fix

// before
if (!endpoint) throw new Error(`Workspace endpoint unavailable for ${selectedId}.`);
// after — wait briefly for hydration then retry once
let endpoint = endpointForWorkspace(workspace);
if (!endpoint) {
  await refreshRouteState();
  endpoint = endpointForWorkspace(workspacesRef.current.find((item) => item.id === selectedId) ?? null);
  if (!endpoint) throw new Error(`Workspace endpoint unavailable for ${selectedId}.`);
}
Defensive patterns

Strategy: validation

Validate before calling

const workspace = workspacesRef.current.find((item) => item.id === selectedId) ?? null;
if (workspace && !endpointForWorkspace(workspace)) {
  await refreshRouteState(); // repopulate endpoints before activating
}

Type guard

function hasEndpoint(w: Workspace | null): boolean {
  return w != null && endpointForWorkspace(w) != null;
}

Try / catch

try {
  await activateWorkspace(selectedId);
} catch (error) {
  if (error.message.startsWith("Workspace endpoint unavailable")) {
    await refreshRouteState();
    await activateWorkspace(selectedId); // retry once
  } else throw error;
}

Prevention

When it happens

Trigger: Selecting/activating a workspace whose endpoint lookup (endpointForWorkspace(workspacesRef.current.find(id))) returns undefined — i.e., the workspace has no remote connection info or local endpoint registered.

Common situations: Workspace list contains stale entries after the local server restarted; a remote workspace was created without completing its connection; workspaces state not yet hydrated when activation is triggered programmatically (e.g., navigateToWorkspaceSession deep link).

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/7605390b6b15cb12. Report an issue: GitHub.