Fix Codex browser startup errors on WSL and Windows
A Codex browser task failed on WSL with Exec format error, broken task paths, and Windows error 267. The repairs that restored Chrome access.
On this page · 12 sections
- 01What we were trying to finish
- 02Four problems survived the move to WSL
- 03Restore interoperability before testing the browser
- 04The task-path repair failed twice
- 05A WSL caller still needs a Windows-compatible request
- 06Tab discovery did not prove permission to inspect a page
- 07Windows error 267 identified the final startup failure
- 08Keep the WSL project and repair the exact Windows aliases
- 09The original browser task finally ran
- 10What the successful run establishes
- 11What I will check first next time
- 12Sources
I asked Codex to compare a local landing page with an experimental version already open in Chrome. I wanted a separate report with the changes highlighted, without touching the application code.
That sounded like a reasonable browser task. It turned into a debugging session involving WSL interoperability, working directories, sandbox metadata, task persistence, and a browser connection that could work in one process while the original task still had no usable tools.
At one point I had to ask the agent whether it had actually checked that we were already in WSL. That was a useful correction to the investigation: verify which process is running where before proposing another environment change.
We eventually produced the comparison. There are two results worth keeping separate: a restricted WSL-to-Windows bridge executed JavaScript and discovered the Chrome tabs; the completed inspection ran later through the official Chrome extension from a fresh Windows agent running with full access, with the project files still in WSL.
What we were trying to finish
The task had a small, concrete acceptance test:
Read both live pages through Chrome.
Compare their sections, copy, and interface examples.
Put numbered highlights and explanations in a separate report.
Keep the application source unchanged.
An installed plugin was only a prerequisite. A successful tab listing was one more step. The task was complete when the agent had inspected the actual pages and delivered the comparison.
I also need to be precise about the name Computer Use. This session's successful browser operations used the Chrome extension backend. The initial Windows desktop-state probes failed; we did not establish a successful general desktop-control session here. Part one records the earlier read-only application-discovery checks.
Four problems survived the move to WSL
The initial Windows execution was already struggling with sandbox setup against a workspace reached through a WSL UNC path. Resetting the JavaScript kernel did not fix it. The required browser service file was present, so repeating the previous marketplace repair would have targeted a problem we had already cleared.
After moving into a WSL agent environment, Linux commands worked, but four things remained broken:
Chrome tools
The task did not have usable Chrome tools.
Repair Windows error 267 identified the final startup failure
Windows executables
Windows executables launched from WSL returned
Exec format error.Saved working directory
The task's saved working directory had been converted incorrectly.
Development server
The local development server was no longer responding.
Restore interoperability before testing the browser
WSL normally supports launching Windows executables from Linux. Microsoft's interoperability documentation describes that boundary and notes that arguments passed to a Windows executable are not automatically rewritten into Windows paths.
On this installation, the standard WSLInterop binary-format registration was absent. We checked whether the WSL configuration explicitly disabled interoperability, then restored the registration. A Windows version command subsequently ran from the WSL shell.
That result established that WSL could start a Windows process again. It said nothing yet about the MCP connection, sandbox setup, or browser permissions.
The development server was another independent repair. We brought it back and checked HTTP responses from both operating-system environments. A persistent user service was added later so that the page stayed available through the remaining task changes. This was local development infrastructure; the landing-page application did not need a feature change.
The task-path repair failed twice
The first repair script closed its connection during initialization. That failure was ours: the standalone process was missing the CODEX_SQLITE_HOME used by the desktop setup.
This installation split its state across filesystems. Some Codex files lived under the mounted Windows profile, while SQLite storage lived in Linux. Starting another app-server process without that distinction did not reproduce the desktop's storage context. Supplying the correct storage location allowed initialization to complete.
The next attempt still failed its acceptance test. Calls to resume the task and update its settings did not result in the expected saved path. A subsequent read returned the old value. The script refused to declare the task repaired.
An offline recovery then waited for the task writer lock, backed up the relevant records, and repaired the corresponding session metadata and SQLite path. A fresh read returned the intended Linux working directory, and the recorded verification showed that the conversation bytes were unchanged.
I am describing that operation as recovery of this installation's internal state. It is not a supported, general task-migration recipe. The useful part to repeat is the verification: stop concurrent writers, preserve a rollback, and read the result through the application after the repair. Editing internal state while a live process still owns it would make the result much harder to trust.
A WSL caller still needs a Windows-compatible request
Once Windows executables could start, the next failure happened inside the request sent to the Windows Node runtime. The workspace was a valid Linux directory, but the Windows receiver rejected its sandbox working-directory URI.
These examples show the distinction:
- Linux workspace
WSL/home/<WSL_USER>/<PROJECT>- Linux-local file URI
WSLfile:///home/<WSL_USER>/<PROJECT>- Windows access to that workspace
Windows\\wsl.localhost\<DISTRO>\home\<WSL_USER>\<PROJECT>
Changing only sandboxCwd was insufficient in this run. Other filesystem entries in the permission profile still used Linux paths. Converting Windows-mounted entries to native drive paths and Linux-native entries to UNC paths passed path validation but still ran into Windows sandbox setup failures.
The diagnostic adapter became more selective. It mapped supported Windows-mounted paths, chose an already authorized Windows results directory, removed write grants for the Linux project, preserved protected-path restrictions, and rejected profiles it could not represent safely. The Windows helper started from an existing Windows Codex directory.
This was useful for the original read-only comparison because its output could live outside the application repository. It did not make every Linux filesystem permission meaningful to a Windows sandbox.
The resulting chain was:
WSL agent
WSLdiagnostic STDIO adapter in WSL
WSLWindows
Windowsnode_repl.exeand Node runtimepackaged browser client and trusted browser service
WindowsChrome extension
Windows
The recorded adapter tests passed, and a restricted JavaScript probe ran successfully. After the runtime received the browser-service mapping and backend configuration, the official Chrome client discovered both requested tabs. The tool result identified the Chrome browser backend.
The agent called the repair installed and tested before the original task could inspect both pages. That claim went beyond what the probe had established.
Tab discovery did not prove permission to inspect a page
A later attempt found that the experimental tab was no longer available in the expected session. Another browser action failed closed because its permission review could not complete.
We did not treat that failure as approval to continue the action. The earlier adapter had proved JavaScript execution and Chrome discovery. It had not proved a complete, authorized inspection through the original task's normal tool connection.
There was a process-lifetime problem as well. A diagnostic subprocess can load a corrected configuration while a task that was already running retains an older connection or tool catalog. A successful probe from the new process cannot answer whether the old task has refreshed.
Windows error 267 identified the final startup failure
After returning to a Windows agent context, the saved Linux-shaped workspace path acquired a Windows drive prefix. The resulting directory did not exist:
Error
The directory name is invalid. (os error 267)Where it fails
Windows startup failure, before MCP initialization.
Cause
Expected Linux workspace: /home/<WSL_USER>/<PROJECT>. Incorrect Windows interpretation: C:\home\<WSL_USER>\<PROJECT>.
Fix, in this order
Add
cwdto the existing[mcp_servers.node_repl]entry, pointing at the existing Windows Codex directory.Add a directory symbolic link at the exact missing Windows path, targeting the real repository through the WSL UNC namespace.
Fixing the MCP launch directory did not resolve the task's workspace path.
Microsoft documents error 267 as ERROR_DIRECTORY. In the local logs, it occurred before MCP initialization. The same executable started successfully from another task with a valid directory.
The process launch directory and the task workspace were two separate values. Codex's MCP configuration documentation defines cwd as the directory used to start a STDIO server. We added that field to the existing server entry, pointing it at the existing Windows Codex directory:
# Relevant field in the existing entry; other settings were preserved.
[mcp_servers.node_repl]
cwd = 'C:\Users\<WINDOWS_USER>\.codex'
The path above is a placeholder for the actual existing directory. It is not a portable value to paste into another installation.
This also explains why changing cwd had been ineffective against the original failure in part one. That earlier error concerned the sandboxCwd metadata attached to a tool call. Error 267 here prevented the server process from starting. The similarly named fields belonged to different stages.
Keep the WSL project and repair the exact Windows aliases
Fixing the MCP launch directory did not resolve the task's workspace path. We added a directory symbolic link at the exact missing Windows path, targeting the real repository through the WSL UNC namespace:
C:\home\<WSL_USER>\<PROJECT>
-> \\wsl.localhost\<DISTRO>\home\<WSL_USER>\<PROJECT>
A second, narrowly scoped alias addressed another task whose mounted-drive path had acquired an extra C:\mnt\c\ prefix. We checked the intended targets before creating either link.
The repository stayed in WSL. These links provided compatibility for the two paths already held by the Windows tasks; they did not implement a general Linux-to-Windows path translator. A source-file hash matched through the repaired workspace path.
This final step did not rewrite the task history or its database again. An isolated native MCP initialization and tool-list probe passed, and a fresh agent subsequently received the official Node REPL tools. That last check closed the gap left by the earlier standalone probes.
The original browser task finally ran
The fresh agent initialized the packaged browser runtime and explicitly selected the Chrome extension backend. The in-app browser was also discoverable, but it was not the backend used for the source-page captures.
One existing local-page tab belonged to a different task. The capture agent opened its own local-page tab. It used the available experimental-design tab and entered presentation mode through the visible controls.
The experimental page also displayed an availability error during the investigation. Once I corrected that on my side, the agent retried it and used the live design. An older exported HTML file had been considered as a fallback; it was not the reference used for the final comparison.
The delivery path was now:
Project files and local development server in WSL
WSLWindows-visible workspace alias
Windowsfresh Windows agent and Windows Node runtime
Windowsofficial Chrome extension backend
Windowslive-page inspection and comparison report
delivered
The report contained twenty comparison image panels across ten sections, using eighteen distinct captures, with twenty-eight observations, numbered highlights, explanations, and image enlargement. A portable HTML copy embedded the images so that the result could be opened later without the report server.
The visual review needed one more correction of its own: animated demonstrations and carousels can show different states. We aligned equivalent template cards, identified animated areas, and documented the different capture scales. The report compared content and components; it did not claim a pixel-perfect diff.
The recorded checks covered all ten desktop sections, image loading, highlight toggles, navigation from a numbered marker to its explanation, and opening and closing enlarged images. Mobile checks covered representative sections and horizontal overflow. The portable copy was checked separately. The application source remained unchanged.
What the successful run establishes
- probe passed
WSL bridge, restricted sandbox
The WSL bridge demonstrated restricted JavaScript execution and Chrome-tab discovery.
Does not show It had not proved a complete, authorized inspection through the original task's normal tool connection.
- delivered
Windows-hosted task, full access
The final Windows-hosted task demonstrated the complete browser inspection and report delivery against a project that remained in WSL.
Does not show The final capture task ran after I explicitly selected full access. Its success therefore does not establish that the same complete workflow passed under the earlier restricted sandbox.
We also did not prove that every existing task refreshed its tools, that the aliases would cover another workspace, or that a later desktop release would preserve this configuration. These were repairs and checks for the installation we had in front of us.
What I will check first next time
I will start with a smaller set of questions, in order:
Which operating system hosts the agent, the MCP server, and the browser? The repository's path alone cannot answer that.
Can WSL launch the required Windows executable, and can Windows start it from the configured directory?
Did the failure happen at process startup, MCP initialization, request validation, service loading, or browser permission review?
Are the configured service files present, and does a fresh process load them?
Does the actual task have working tools, rather than only a successful diagnostic subprocess?
Can that task perform one authorized read of the intended page and produce the requested result?
I would also verify a saved-path change immediately instead of inferring success from the update call. That check caught our incomplete repair before we built more assumptions on it.
For the related upstream reports on WSL browser availability and malformed plugin paths, see my Codex issue reproductions.
Sources
This note is based on the September 7–8 investigation, local startup errors, the task-path repair receipts, adapter-test results, official browser-tool responses, and the final comparison's capture manifest and QA records. The Codex agent helped collect and cross-check that evidence.