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
- Refresh the workspace list (refreshRouteState) so endpoints are populated before activating.
- Re-establish the workspace's connection (save/validate its remote connection) if it is a remote workspace.
- Check endpointForWorkspace logic/data for the missing workspace and correct stale entries.
- 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
- Refresh workspace state after server restarts before accepting activation.
- Guard deep-link activation behind workspace list hydration.
- Prune stale workspaces whose endpoints can no longer be resolved.
- Complete remote-connection setup before surfacing a workspace as activatable.
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
- Workspace endpoint is unavailable; attachments could not be
- This cloud provider has not been imported into the workspace
- OpenWork server cannot read MCP config for this workspace.
- Cannot create a task without a selected workspace.
- Workspace path is unavailable; attachments could not be copi
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/7605390b6b15cb12.
Report an issue: GitHub.