open-webui / open-webui/computer
bug: image previews never render on Windows — frontend sends backslash paths to `/api/workspace/files/serve`
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
- On Windows, open a workspace and put a PNG in it.
- Ask the agent to
display_filethat PNG (or open it from the file browser). - 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.
Backend — routers/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
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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