[GH-ISSUE #79] Chat renders twice (wrong workspace then correct) when opening a chat in a different workspace #36

Closed
opened 2026-10-18 14:02:15 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @chhotu-claw on GitHub (Jun 24, 2026).
Original GitHub issue: https://github.com/open-webui/computer/issues/79

Summary

Opening a chat that lives in a different workspace (e.g. clicking it in the sidebar) renders the chat twice: it first opens in the current (wrong) workspace, then re-renders in the correct workspace once the switch completes. Visible as a double-load / flash of the chat window on every cross-workspace navigation.

Steps to reproduce

  1. Open a chat in workspace A.
  2. In the sidebar, click a chat that belongs to workspace B.
  3. The chat window loads, briefly against workspace A, then loads again under workspace B.

Expected

A single render: switch to workspace B, then open the chat in B.

Root cause

In src/routes/+page.svelte, the URL-driven workspace effect both reads and writes lastLoadedPath, which is $state:

let lastLoadedPath = $state<string | null>(null);

$effect(() => {
    const workspacePath = $page.url.searchParams.get('workspace');
    ...
    if (workspacePath && workspacePath !== lastLoadedPath) {
        lastLoadedPath = workspacePath;            // (1) synchronous write to $state
        loadWorkspace(workspacePath).then(async () => {
            ...
            processIntentParams();                 // (3) correct: runs after load
        });
    } else if (workspacePath && workspacePath === lastLoadedPath) {
        processIntentParams();                     // (2) runs immediately
    }
    ...
});

Writing lastLoadedPath at (1) re-triggers the effect synchronously (it's reactive state the effect reads). On that re-run workspacePath === lastLoadedPath, so branch (2) calls processIntentParams() immediately — but loadWorkspace() from the first run is still in flight, so currentWorkspace is still the old workspace. The openChat intent is therefore applied against the wrong workspace (render #1). When loadWorkspace() resolves, the workspace switches and (3) opens the chat again in the correct workspace (render #2).

Suggested fix

Only process intents in the immediate branch when the target workspace is actually current; otherwise let the in-flight loadWorkspace().then() handle it:

} else if (workspacePath && workspacePath === lastLoadedPath) {
    if (get(currentWorkspace)?.path === workspacePath) processIntentParams();
}

This preserves the fast path for same-workspace navigation (chat-to-chat within the current workspace) while preventing intents from being applied against a stale workspace during a cross-workspace switch. Single render in all cases.

(Making lastLoadedPath a plain let instead of $state also resolves it, by removing the spurious self-retrigger — but the guard is the smaller, more targeted change.)

Originally created by @chhotu-claw on GitHub (Jun 24, 2026). Original GitHub issue: https://github.com/open-webui/computer/issues/79 ## Summary Opening a chat that lives in a **different workspace** (e.g. clicking it in the sidebar) renders the chat **twice**: it first opens in the *current* (wrong) workspace, then re-renders in the correct workspace once the switch completes. Visible as a double-load / flash of the chat window on every cross-workspace navigation. ## Steps to reproduce 1. Open a chat in workspace **A**. 2. In the sidebar, click a chat that belongs to workspace **B**. 3. The chat window loads, briefly against workspace A, then loads again under workspace B. ## Expected A single render: switch to workspace B, then open the chat in B. ## Root cause In `src/routes/+page.svelte`, the URL-driven workspace effect both **reads and writes** `lastLoadedPath`, which is `$state`: ```ts let lastLoadedPath = $state<string | null>(null); $effect(() => { const workspacePath = $page.url.searchParams.get('workspace'); ... if (workspacePath && workspacePath !== lastLoadedPath) { lastLoadedPath = workspacePath; // (1) synchronous write to $state loadWorkspace(workspacePath).then(async () => { ... processIntentParams(); // (3) correct: runs after load }); } else if (workspacePath && workspacePath === lastLoadedPath) { processIntentParams(); // (2) runs immediately } ... }); ``` Writing `lastLoadedPath` at (1) **re-triggers the effect synchronously** (it's reactive state the effect reads). On that re-run `workspacePath === lastLoadedPath`, so branch (2) calls `processIntentParams()` **immediately** — but `loadWorkspace()` from the first run is still in flight, so `currentWorkspace` is still the **old** workspace. The `openChat` intent is therefore applied against the wrong workspace (render #1). When `loadWorkspace()` resolves, the workspace switches and (3) opens the chat again in the correct workspace (render #2). ## Suggested fix Only process intents in the immediate branch when the target workspace is actually current; otherwise let the in-flight `loadWorkspace().then()` handle it: ```ts } else if (workspacePath && workspacePath === lastLoadedPath) { if (get(currentWorkspace)?.path === workspacePath) processIntentParams(); } ``` This preserves the fast path for same-workspace navigation (chat-to-chat within the current workspace) while preventing intents from being applied against a stale workspace during a cross-workspace switch. Single render in all cases. (Making `lastLoadedPath` a plain `let` instead of `$state` also resolves it, by removing the spurious self-retrigger — but the guard is the smaller, more targeted change.)
Author
Owner

@tjbck commented on GitHub (Jun 25, 2026):

Should be addressed!

<!-- gh-comment-id:4800977868 --> @tjbck commented on GitHub (Jun 25, 2026): Should be addressed!
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
open-webui/computer#36
No description provided.