Skip to content

Files preview shows "Unable to load file preview" on a New thread draft (assets.createUrl resolves workspace via a draft thread id) #17273

Description

@mths-mcfs

Summary

Opening an HTML file in the Files preview panel from a "New thread" screen fails with "Unable to load file preview". The thread has not been created on the server yet. The client asks for the asset as a workspace-file keyed by the draft thread id, so the server cannot resolve the workspace.

The server already has a draft-workspace-file resource that takes cwd and path. Requesting the same file that way returns the correct content.

Environment

  • T3 Code 0.0.46-nightly.20261008.2819
  • Linux, server started with t3 serve --host ..., web client in the browser
  • Project with a git workspace root, file under wireframes/*.html

Steps to reproduce

(Inferred from the screenshot and logs. I did not re-click through the UI.)

  1. Open a project and start a "New thread" (draft, no message sent yet).
  2. Open an HTML file from the workspace in the Files preview panel.
  3. The panel shows "Unable to load file preview".

Expected

The preview loads the file, as it does in an existing thread.

Actual

The panel shows "Unable to load file preview" with no further detail. The server trace has three ws.rpc.assets.createUrl failures within about 25 seconds, all with this cause chain:

AssetWorkspaceContextResolutionError: Failed to resolve workspace context.
[cause]: OrchestratorProjectionError: Failed to load orchestration projection for thread 276d1604-...
[cause]: ProjectionStoreThreadNotFoundError: No orchestration projection exists for thread 276d1604-...

That thread id does not exist on the server (t3_thread_read returns thread_not_found).

Diagnosis

I reproduced this outside the UI with a script that calls assets.createUrl over the WebSocket RPC. It uses a short-lived, read-only session (filesystem:read, orchestration:read), revoked afterwards. The same file gave two results:

Resource sent Result
{ _tag: "workspace-file", threadId: <draft id>, path } Fails with the error chain above
{ _tag: "draft-workspace-file", cwd: <workspace root>, path } HTTP 200, 60131 bytes, identical to the local file

So the file, its permissions and the signed URL are fine. The panel uses the wrong resource kind while the thread is still a draft. The assets.createUrl handler in the server bundle already has a draft-workspace-file branch that passes workspaceRoot: input.resource.cwd.

Related issues and PRs

I found no issue or PR for this case. The closest ones cover other causes:

Workaround

Open the file from an existing thread in the same project and directory.

Activity

  1. juliusmarminge commented on Oct 8, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Thanks for the detailed report and the RPC comparison. The code on main (805967a87) matches your diagnosis. I checked this by reading the code, not by running the app.

    Cause

    Scope (from the code)

    • Workspace images in a draft probably fail the same way, with "Unable to load workspace image."
    • The panel's "open in browser" action probably does too, because openFileInPreview.ts:117-121 builds the same workspace-file resource.
    • Video and audio send an absolute media-file path. The server serves those without a thread lookup (ws.ts:2709), so they should work in drafts.

    Possible fix (untested)

    • ChatView already passes the draft's workspace root as cwd (ChatView.tsx:4224 and :11070), and it knows whether the thread is a draft through isServerThread (:2112).
    • FilePreviewPanel could take a draft flag. For a file inside the workspace, it would then send { _tag: "draft-workspace-file", cwd, path: <workspace-relative path> } instead of workspace-file, the same way mobile does, and openFileInPreview would get the same branch.
    • Keeping the path relative matters for HTML. An absolute draft path is served as a single file (AssetAccess.ts:527-537), so the page couldn't load its sibling assets.
    • draft-workspace-file needs the same filesystem:read scope as workspace-file and media-file (RpcAuthorization.ts:249-257), so switching to it shouldn't let a session read anything it can't already reach with absolute media-file paths.

    Related: I didn't find a duplicate or an open PR for this. #15929 (chat HTML/PDF links on web clients) and #16950/#16044 cover nearby code paths but not drafts.

    Your workaround of opening the file from an existing thread in the same project makes sense until this is fixed.

  2. added
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions