Repository navigation
[Bug]: 0.0.41-nightly desktop UI "T3 Code could not load." — t3code:// serves truncated asset (SyntaxError: Unexpected end of input) #11523
Description
Activity
Triage
Accepted as a critical desktop launch bug.
v0.0.41-nightly.20260913.1625(commit2db675aef) Linux AppImage opens a window, the backend becomes ready, then the renderer dies and paints “T3 Code could not load.”This is not a duplicate of #10719. That issue is a parsed ESM chunk missing
export { t }. This one is a parse error (SyntaxError: Unexpected end of input) on thet3code://apppath only. It is also not #10517 (blank window because the backend never serves the page).T3 Code failed to start. SyntaxError: Unexpected end of input source: t3code://app/assets/index-DRGRqw-K.js (2)The same machine, profile, and launch flags work on
v0.0.41-nightly.20260912.1612. Clean--user-data-dirand--appimage-extractboth still fail, so this is not a poisoned HTTP cache or squashfs/FUSE truncation.What the code does
Production desktop loads
t3code://app/(apps/desktop/src/window/DesktopWindow.ts→getDesktopUrl).apps/desktop/src/electron/ElectronProtocol.tsregisters that scheme (stream: true) andprotocol.handles every renderer request byElectron.net.fetching the local backend, then re-wrapping the body to attach CSP:return new Response(response.body, { status, statusText, headers });
The backend serves
apps/server/dist/clientwithHttpServerResponse.streaminapps/server/src/http.ts, behind globalHttpMiddleware.compression()(gzip/br, min 1024 bytes).Startup is:
- Packaged
index.htmlloads the Vite entry (src/bootstrap.ts) bootstrap.tsdoesimport("./main").catch(showBootError)apps/web/src/lib/bootError.tslogsT3 Code failed to start.and paints “T3 Code could not load.” (the SyntaxError is DEV-only in the UI, which is why it only appears under--enable-logging)
The log
source: …/index-DRGRqw-K.js (2)is theconsole.errorinsideshowBootError. That entry module ran. The SyntaxError is from whateverimport("./main")fetched — typically the main hashed chunk or another/assets/*.js— not proof thatindex-DRGRqw-K.jsitself was truncated. Chromium often attributes a failedimport()to the importer.That matches the reporter’s checks:
index-DRGRqw-K.jsis valid inapp.asar(7971 bytes) and overhttp://127.0.0.1:3773/assets/…(Chrome can load that URL and reach pairing). The HTTP graph is good; the custom-protocol hop is not.stream: trueplus re-wrapping anet.fetchstream while copyingContent-Length/Content-Encodingis a known Electron custom-protocol footgun (truncated body, or gzip/length mismatch after Chromium decodes). #9023 enabled streaming for media; it applies to JS modules too.Why this nightly?
ElectronProtocol.tsand statichttp.tsare unchanged between20260912.1612and20260913.1625. Electron is still 44.1.0. Desktop commits in the window (#7599 quit timeout, #7110 preview UA, paste-as-text from #11442) are not on the renderer serve path. The web client did change substantially (composer attachments, subagent rows, a11y headings, diffs), so chunk sizes/graphs changed on top of the existing stream proxy. A latent protocol-stream bug becoming 100% on a larger or differently chunked bundle is the best fit.Related
- [Bug]: T3 Code 0.0.40 desktop UI: "T3 Code could not load" #10719 — same boot screen /
t3code://app; different error (missing export) - [Bug]: Backend startup crashes leave desktop blank with no visible error #10517 — blank window; backend never serves
- [Bug]: T3 Code opens a blank window when the Linux credential store is locked #9239 / fix(desktop): app no longer opens a blank window when the Linux credential store is locked #9246 — Linux credential-store blank window
- AppImage auto-update leaves a 0-byte binary and the app never launches again #10685 — AppImage auto-update leaves a 0-byte binary
- [Bug]: Failed startup session probe bricks the app — fatal, sticky error in root beforeLoad with no recovery #3513 — sticky error after the renderer has loaded
- fix(media): preview host files and stream videos across clients #9023 — added
stream: true(already in the working nightly) - Fix Electron dev and packaged renderer startup #3557 — protocol proxy, header stripping, GET retries
- feat: add inline file previews and attachment chips across surfaces #11265 — CSP
frame-srconly; already in20260912.1612 - feat(desktop): serve packaged renderer locally #8101 — closed; serve packaged renderer from disk instead of proxying HTTP
No open PR for this truncation.
Next step
- On the failing AppImage, compare all
/assets/*.js(especially the target ofindex-*.js’simport()) overt3code://appvs HTTP vsapp.asar— byte length and a tail snippet, not onlyindex-DRGRqw-K.js. - Fix the protocol handler: buffer JS/CSS/HTML (
arrayBuffer()), drop staleContent-Encoding, setContent-Lengthto the decoded size; keep streaming for audio/video only. Optionally revisit feat(desktop): serve packaged renderer locally #8101 (serve packaged files from the asar path). - Check macOS and Windows
v0.0.41-nightly.20260913.1625— samet3code://path.
Workaround:
v0.0.41-nightly.20260912.1612.- Packaged
- addedbugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.acceptedfeature request acceptedfeature request acceptedvia-triageFiled through npx t3 triageFiled through npx t3 triage
on Sep 13, 2026 Measured this from the affected build using the renderer's own DevTools (Electron
--remote-debugging-port). Thesource:in the error is misleading:assets/index-DRGRqw-K.jsis not the broken file.showBootErrorlives in that chunk, so the caughtSyntaxErroris attributed there. The truncated files are the large chunks.Fetching each
/assets/*.jsfrom the renderer and comparingbyteLengthto the entry size inapp.asar:asset received over t3code://expected assets/main-CFHzQs_8.js246112 704945 assets/utils-DmcWaRy7.js260917 755787 assets/server-CSx755AA.js0 19224 Small assets are intact —
assets/index-DRGRqw-K.jsis 7971/7971 and its sha256 matches the copy insideapp.asar:51cfaf46373be9425c39b51bb878ed9aa7e1757dd8367e9067ff8246aba26c99The same backend serves the full files over its HTTP listener, so the truncation is specific to the
t3code://path and only hits larger bodies:$ curl -s -o /dev/null -w '%{size_download}' http://127.0.0.1:3773/assets/main-CFHzQs_8.js 704945Same measurement against the previous nightly (
v0.0.41-nightly.20260912.1612), same machine, same flags, same profile setup: 256 assets loaded throught3code://, 0 mismatches, no boot error. The working build even ships larger chunks (utils755380,main700010,heic-to~3 MB), so it is not a simple size limit either.Both builds negotiate the same encodings (
br/gzip, nozstd), so it does not appear to be zstd:# broken build, /assets/utils-DmcWaRy7.js req=identity -> content-length: 755787 req=br -> content-encoding: br req=zstd -> content-length: 755787 # not compressed req=gzip -> content-encoding: gzip
So: regression between
20260912.1612and20260913.1625in the delivery of large assets overt3code://, even though nothing landed inapps/desktop/src/electron/ElectronProtocol.tsorapps/server/src/http.tsin that window.Minimal way to reproduce the measurement (app launched with
--remote-debugging-port=9333), run in the page context via CDPRuntime.evaluate:const r = await fetch("t3code://app/assets/main-CFHzQs_8.js"); (await r.arrayBuffer()).byteLength; // 246112 here, 704945 expected
Workaround still: use
v0.0.41-nightly.20260912.1612.
Before submitting
Area
apps/desktop
Steps to reproduce
Download
T3-Code-0.0.41-nightly.20260913.1625-x86_64.AppImage(Linux x86_64),chmod +xit.Launch it, with the renderer console visible:
The window opens, the backend becomes ready, then the UI is replaced by "T3 Code could not load."
The renderer console reports a truncated module:
Reproduces 100% of launches. I also tried to rule out local causes:
--user-data-dirpointed at an empty temp dir: same error (rules out a poisoned HTTP cache).--appimage-extractand ran the extractedt3codebinary: same error (rules out squashfs/FUSE truncation).Expected behavior
The bundled web client loads through
t3code://app/...and the desktop reaches the normal UI, as it does on the previous nightlyv0.0.41-nightly.20260912.1612.Actual behavior
The bootstrap module is served truncated over the custom
t3code://protocol, sobootstrap.ts'simport("./main").catch(showBootError)fails withSyntaxError: Unexpected end of inputand paints the boot-error screen.The same asset is intact in the package and over the backend HTTP URL, so the truncation is specific to the
t3code://appserving path in this build:app.asar,apps/server/dist/client/assets/index-DRGRqw-K.jsis present and valid — 7971 bytes, ends with//# sourceMappingURL=index-DRGRqw-K.js.map.GET http://127.0.0.1:3773/assets/index-DRGRqw-K.jsreturns HTTP 200,content-length: 7971, valid JS (I can load the same URL in Chrome and the app reaches the UI/pairing screen).t3code://app/assets/index-DRGRqw-K.jsand the module fails to parse.This is a different symptom from #10719 (0.0.40,
does not provide an export named 't'inter-chunk mismatch). The failure here is a parse error, which is what you get from a truncated/mangled body rather than a missing export.Impact
Blocks work completely
Version or commit
v0.0.41-nightly.20260913.1625 (commit 2db675a)
Environment
T3-Code-0.0.41-nightly.20260913.1625-x86_64.AppImage, 188486467 bytes)--user-data-dirv0.0.41-nightly.20260912.1612works on the same machine, same profile, same launch flagsLogs or stack traces
Desktop log (backend comes up fine, window is created, then the renderer boot fails):
Asset status compared across the two paths (broken build):
Screenshots, recordings, or supporting files
Screenshot of the boot-error screen attached in the report ("T3 Code could not load." with the Reload button). Happy to provide the full
--enable-logging=stderrcapture if useful.Workaround
Downgrade to the previous nightly, which launches normally:
v0.0.41-nightly.20260912.1612→T3-Code-0.0.41-nightly.20260912.1612-x86_64.AppImagehttps://github.com/pingdotgg/t3code/releases/download/v0.0.41-nightly.20260912.1612/T3-Code-0.0.41-nightly.20260912.1612-x86_64.AppImageRelated: #10719 (0.0.40 desktop boot failure — same
t3code://appserving path, different error).