Codex Desktop mini window popout renders Application Error on macOS 26.4
Summary
On Codex Desktop for macOS, the thread mini-window/popout no longer renders the conversation. It opens a popout window, but the popout immediately displays the app error boundary instead of the thread content.
Local investigation also found a separate terminal-font issue in the same app install: the terminal was configured to use Geist Mono, but that font was not installed locally, so it silently fell back to another monospace font. Installing font-geist-mono resolves that local font issue.
Environment
- App: Codex Desktop from
/Applications/Codex.app - Codex app version:
26.415.21839 CFBundleVersion:1763- Bundle id:
com.openai.codex - macOS:
26.4/ build25E246 - Hardware: Apple M4, arm64
- Electron:
41.2.0 - Chrome:
146.0.7680.179 - Node:
24.14.0 - Sentry release in local scope:
codex@26.415.21839 - Tags in local Sentry scope:
buildFlavor=prod,bundle=webview,host=app,preRelease=false - Active app-server process:
/Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled
There is also an older ~/Applications/Codex.app at 26.409.20454, but the running process is the newer /Applications/Codex.app build above.
Reproduction steps
- Open a local Codex Desktop thread.
- Use the thread action to open the mini window / popout.
- Observe the popout window.
Expected behavior
The popout should render the selected thread in the mini-window view.
Actual behavior
The popout opens, but it shows the app's error boundary / Application Error message instead of thread content.
The local Sentry scope captured this renderer error:
Error: Thread context is unavailable for non-thread routes
React ErrorBoundary Error
The stack in the Sentry scope points into the production webview bundle, including:
app://-/assets/index-kiOLixS3.js
app://-/assets/use-model-settings-DxAqUfLj.js
app://-/assets/vscode-api-BM-wzBx9.js
app://-/assets/app-server-manager-signals-AIlnLWLG.js
Investigation notes
I extracted the running app bundle from:
/Applications/Codex.app/Contents/Resources/app.asar
The relevant compiled webview bundle is:
webview/assets/index-kiOLixS3.js
From the extracted production bundle:
- The mini-window action dispatches
open-thread-overlaywithhostId,conversationId, andtitle. - It then calls
maybe-resume-conversationandbroadcast-conversation-snapshotfor the selected conversation. - The overlay route is
/thread-overlay/:conversationId. - The overlay route component renders the thread content with
allowMissingConversation: trueandshowExternalFooter: true. - A route matching helper does recognize
/thread-overlay/:conversationIdas having a conversation id. - However, the runtime error indicates that a component or hook below the overlay route is still calling thread-context-only code while the current route is considered a non-thread route.
That suggests the regression is likely one of these:
/thread-overlay/:conversationIdis missing the same thread context provider used by normal thread routes such as/local/:conversationIdor/remote/:conversationId.- A child component now rendered in the overlay path, possibly a footer/model/settings/tooling component, assumes thread context and calls the guarded thread-context hook.
- The route classification/helper that gates thread context does not include the overlay route even though the overlay route has a
conversationId.
Suggested fix direction
One of the following should fix the popout path:
- Wrap
/thread-overlay/:conversationIdin the same thread context provider used by the normal thread routes. - Or make overlay-specific children avoid the guarded thread-context hook and use explicit
conversationId/hostIdprops instead. - Add a regression test that mounts or navigates to
/thread-overlay/:conversationIdand verifies it does not render the error boundary.
Duplicate search
I searched open and closed issues/PRs for the exact error string and related mini-window/popout terms and did not find an obvious duplicate for this specific macOS Desktop error:
"Thread context is unavailable for non-thread routes"
"Open in mini window"
"thread-overlay"
"popout"
A related but different issue exists for Windows popout resizing (#16180), but this report is about the macOS popout crashing with the thread-context error.
Related local terminal-font finding
This appears separate from the popout crash, but happened in the same app install.
The app state had the light theme Code font set to:
"Geist Mono", ui-monospace, "SFMono-Regular"
Before installing the font, local font enumeration did not show Geist Mono, so the integrated terminal could not render with the configured font and silently fell back. Installing the font fixed local font resolution:
brew install --cask font-geist-mono
fc-list | rg -i 'Geist Mono|GeistMono'
After installation, Geist Mono is visible under ~/Library/Fonts/ and the terminal should use it after an app/window refresh.
This aligns with the behavior discussed in #10620: the terminal uses the configured Code font. A small product improvement would be to surface a warning or diagnostic when the configured UI/Code font is unavailable on the system.
4 Comments
Additional local investigation / candidate fix:
I attempted a local hotfix against the packaged renderer bundle in
26.415.21839. The crash appears to happen during overlay bootstrap because the renderer route scope is computed fromwindow.location.pathnamebefore theinitialRoute=/thread-overlay/<conversationId>navigation has settled.In the packaged bundle, the route-scope classifier in
webview/assets/diff-view-mode-CDxb8Wc9.jsmaps these paths to route kinds:The desktop main process creates the HUD window with
initialRoute:Other overlay-aware code already checks
initialRoutedirectly, but this route-scope classifier does not. If the packaged app initially loads at/or/index.htmlwith?initialRoute=/thread-overlay/<id>, the route scope can briefly behome/otherinstead oflocal-thread, and thread-context atoms then throw:A local candidate patch was to make the route-scope classifier normalize the bootstrap path through
initialRoutebefore matching thread routes:I verified this patch is syntactically valid when applied to the extracted bundle and that it changes only the route classifier.
Follow-up from local validation of the workaround on macOS 26.4 / Codex 26.415.21839:
The popout route patch alone was not sufficient for a locally modified macOS app bundle because Electron and hardened runtime enforcement add two more requirements:
Contents/Info.plisthasElectronAsarIntegrityforResources/app.asar. After changing and repackingapp.asar, Electron aborts at startup unless this hash is updated to the SHA-256 of the ASAR header JSON.node_modules/better-sqlite3/build/Release/better_sqlite3.nodeandnode_modules/node-pty/build/Release/pty.nodeexisted inside the packed ASAR and were still OpenAI-signed. Electron extracts them to temp paths such as/var/folders/.../T/.com.openai.codex.*; dyld then rejects them withmapping process and mapped file (non-platform) have different Team IDsif the outer app has been locally re-signed.Validated local workaround:
?initialRoute=/thread-overlay/<id>as the effective pathname during compact/popout bootstrap.better_sqlite3.node,pty.node, andspawn-helperif present).app.asar.ElectronAsarIntegrity.Resources/app.asar.hashto the SHA-256 of the repacked ASAR header JSON, not the raw file hash.After that, direct launch succeeded, no new crash report was written, and the runtime-extracted temp
better_sqlite3bundle showed the same TeamIdentifier as the outer app.Follow-up from local patch testing: the launch/signing side is now separate from the remaining popout error.
The popout error is reproducible as a renderer route-scope mismatch. The compact/popout window can load through
app://-/index.html?initialRoute=..., and the route scope classifier can still classify popout routes asother. Components in the popout then read the thread/workspace context atoms and hit:The local patch that should address this has two parts:
/hotkey-window->home/hotkey-window/thread/:conversationId->local-thread/hotkey-window/remote/:taskId->remote-threadinitialRoutehandling when the actual browser pathname is/or/index.html.otherroute returns the same home/workspace context instead of throwing during compact-window startup or transition. This prevents the red error boundary while still allowing proper thread context when the route is classified correctly.Local validation after patching the packaged app:
The latest local ASAR integrity hash after this route/context patch is:
This is still a local binary patch rather than an upstream source PR, but it narrows the product fix to route classification for compact/hotkey popout windows plus a non-crashing context fallback.
This was fixed with 26.415.30602