open-webui / open-webui/computer

bug: image previews never render on Windows — frontend sends backslash paths to `/api/workspace/files/serve`

Open
#246 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
569
Forks
79
PR merge metrics
No merged PRs in 30d

Description

Version: 0.9.21 · OS: Windows 11 · Browser: Chrome

Summary

On Windows, no image ever renders inline. display_file draws the viewer panel — title bar, zoom
controls, 100% — but the image itself is a broken-image icon, and the size readout shows 0 B.

The backend is fine. The frontend builds the URL from a raw Windows path, without converting
backslashes to forward slashes and without URL-encoding
, while the serve endpoint expects
forward slashes — as its own comment says.

Reproduce

  1. On Windows, open a workspace and put a PNG in it.
  2. Ask the agent to display_file that PNG (or open it from the file browser).
  3. The viewer frame appears; the image is broken; size reads 0 B.

Root cause

Frontend_app/immutable/nodes/2.*.js:

`/api/workspace/files/serve/${n.filePath.startsWith('/') ? n.filePath.slice(1) : n.filePath}`

n.filePath on Windows is e.g. C:\Users\user\workspace\example.png (confirmed — it appears
verbatim as the broken image's alt text). It is interpolated raw: no separator normalisation,
no encoding.

Backendrouters/workspace.py:

@router.get("/serve/{file_path:path}")
async def serve_static(file_path: str):
    # Windows paths arrive as "C:/Users/..." - don't prepend /
    if len(file_path) >= 2 and file_path[1] == ":":
        target = Path(file_path).resolve()
    else:
        target = Path("/" + file_path).resolve()

The comment states the contract — C:/Users/..., forward slashes — which the frontend does
not meet.

Evidence the backend is correct

This URL, in a logged-in browser, renders the image correctly:

http://127.0.0.1:8000/api/workspace/files/serve/C:/Users/user/workspace/example.png

Same file, same session, forward slashes instead of backslashes. So routing, auth, MIME detection
and streaming all work; only the URL the frontend builds is wrong.

Suggested fix

Normalise separators before interpolating, and encode each segment:

const p = n.filePath.replace(/\\/g, '/');
const url = `/api/workspace/files/serve/${p.split('/').map(encodeURIComponent).join('/')}`;

Encoding also fixes paths containing spaces, # or ?, which will fail on every platform.

Related: the bundle already has a resolver, de(), which prefers full_path, falls back to
path, and joins relative paths to the workspace root. The image viewer bypasses it — and de()
does not normalise separators either, so both call sites likely need the same treatment.

Workaround in use

Until this is fixed upstream, we patch the built bundle in place, rewriting the interpolation to
normalise separators. It works, but it is a stopgap: an upgrade replaces the bundle and silently
reverts it
, so the patch has to be re-applied and verified after every update. A fix in the
source is the real answer.

Anyone hitting this before a release can also open the file directly at
/api/workspace/files/view?path=<url-encoded absolute path>, which serves correctly.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the source that produces _app/immutable/nodes/2.*.js and inspect the image viewer URL and the de() resolver. Compare their path handling with the contract in routers/workspace.py. Done means Windows image previews work and paths containing backslashes, spaces, #, or ? are sent as valid encoded URLs.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, python
Domain
api, backend, frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.