Computer Use on Windows: get_window_state fails with `node_repl exec context not found`
Open 💬 5 comments Opened Aug 6, 2026 by nickcybela
💡 Likely answer: A maintainer (github-actions[bot], contributor)
responded on this thread — see the highlighted reply below.
Summary
Computer Use can discover an allowed Windows desktop app and its window, but it cannot inspect or control the returned window. Every state capture fails immediately with:
Error: node_repl exec context not found
Environment
- Windows desktop
- ChatGPT/Codex desktop app build:
26.730.61639 - Bundled Computer Use plugin build:
26.730.61639 - Target tested: Adobe Premiere Pro 2026
- Computer Use invoked explicitly with
@Computer
Steps to reproduce
- Install and enable the bundled Computer Use plugin.
- Open a Windows desktop app.
- Invoke
@Computerand ask it to inspect/control that app. - Initialize
@oai/skythrough the bundlednode_repl. - Call
sky.list_apps().
- The target app and exactly one window are returned successfully.
- Rehydrate the exact returned window with
sky.get_window({ id, app }), then call either:
sky.get_window_state({ window, include_screenshot: true, include_text: false }), orsky.get_window_state({ window, include_screenshot: false, include_text: true }).
Actual result
Both screenshot-backed and text-only state capture fail with:
Error: node_repl exec context not found
No input reaches the target app.
Troubleshooting already attempted
- Explicitly invoked the installed Computer Use plugin with
@Computer. - Added the exact app identifier to
[computer_use.windows].always_allowed_app_ids. - Restarted the Codex desktop app.
- Refreshed app/window discovery and retried once using the exact newly returned window.
- Confirmed
sky.list_apps()still succeeds after restart. - Confirmed
nodeRepl.requestMetaexists, while the execution/elicitation context required by the Computer Use operation appears unavailable.
Expected result
sky.get_window_state() should return the selected window's screenshot or accessibility state so Computer Use can proceed.
Impact
Computer Use can enumerate Windows apps but cannot inspect or operate an already allowed target app, blocking all desktop GUI automation beyond discovery.
5 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Root cause and workaround: the Computer Use helper transport is bound to the exec context that spawned it
1. Summary
node_repl exec context not foundon Computer Use calls is caused by the persistent helpertransport outliving the
AsyncLocalStorageexec context in which it was created.The transport holds a handle to a long-lived
codex-computer-use.exechild process. Thatprocess and its streams are async resources tagged with whichever exec first called
request(). A callback from the helper back into the kernel then resolves against thatoriginating exec. From any later exec,
execState.id !== activeExecIdand the kernel throws.(Both elicitation and image emission run through this path; §3 explains why we could not
isolate which one is responsible.)
A one-line workaround exists today:
await sky.transport.close()at the start of each newJS call.
js_resetis not required.2. Environment
cua_noderuntime 0.0.6/20260723162306-088049353ddc, Node 24.14.0,@oai/sky0.6.2Independently reported on build 26.730.61639 against Adobe Premiere Pro (this issue), so it is
neither app-specific nor user-specific and has survived a version bump.
3. Mechanism
The guard, from
node_repl.exe:The transport, from
@oai/sky/dist/.../windows/internal/helper_transport.js(deobfuscated):close()nulls#child; the nextrequest()spawns a fresh helper inside the currentexec, so its async resources carry the current exec's tag. That is exactly why closing
recovers without a kernel reset.
Why only some methods fail. In the reproduced, already-approved path,
list_apps()andget_window()behaved as request/response operations and survived across execs.get_window_state()exercised the failing path — notecreateElicitationthreaded throughevery
request(), and the stringfailed to reply to node_repl emit_image requestinnode_repl.exe. The evidence supports a helper→kernel callback as the discriminator, althoughit does not yet isolate whether elicitation, image emission, or another callback is responsible.
4. Why #37180 and #37281 look like different bugs
Two throw sites share one message:
| Site | Condition | Symptom |
|---|---|---|
|
execState == null| no store at all — a callback outside any exec | #37180: fails on the firstlaunch_app, in the approval/elicitation callback ||
execState.id !== activeExecId| store exists, belongs to a prior exec | #37281: succeeds once, fails on subsequent calls |The two reports are consistent with the same underlying defect — a helper→kernel callback
resolving against the wrong exec — reached from two directions. We reproduced the second-row
path; the first-row mapping remains an inference from #37180 and the two shipped throw sites.
5. Evidence
Runtime (Codex), all timestamps UTC:
js_reset,list_apps()succeeded at22:12:32.236, and a following separate call containing only
1 + 1returned2at22:12:36.532.
list_apps()calls across distinct execs allsucceeded (22:12:51.011, 22:12:57.126, 22:13:02.473).
get_window_state()succeeded at 22:13:54.092, then failed in the next call with the contexterror. Two
get_window_state()calls inside one exec both succeeded(22:14:27.318–22:14:27.711).
get_window({id, app})succeeded at 22:14:06.992, andget_window_state()on that rehydrated window still failed.await import("@oai/sky")in a later exec returns the same singleton(
sameSingleton: true); state capture still failed.js_resetclearsglobalThis({"typeofSky":"undefined","hasOwnSky":false}), so re-importis mandatory with that approach.
await sky.transport.close()thenget_window_state()→ succeeded 22:19:21.762 with nojs_reset. Reusing that new transport in the following exec failed again. Closing againrecovered at 22:19:34.821.
transport.close()followed by a text-onlyget_window_state()against the same returnedNotepad++ window. All 12 succeeded. No
codex-computer-use.exeprocess existed before therun, exactly one existed after cycle 12, and none remained after a final
transport.close().This found no helper-process accumulation; it is not a proof against every possible memory
or handle leak.
get_window_state({include_screenshot:false, include_text:false})cannot isolate acallback-free state path: the API rejects it with
get_window_state must request.include_text, include_screenshot, or both
Static / external (Claude):
~/.codex/node_repl/active_execs/live ~1 second, fresh UUID perJS call, e.g.
{"execId":"b625ec45-...","nodeReplPid":19300,"kernelPid":10452,...}.node_repl.exe(supervisor) →node.exe(V8 kernel) →codex-computer-use.exe(helper). The helper is a child of the kernel.@oai/sky's client is a module-level singleton with no invalidation path (sky.js, 778bytes:
let n = null; ... return n || (n = create_client(...))). This is why re-import doesnot refresh it — but it is not the root cause; the transport underneath is.
Safety / UI sanity check. The workaround still routes every supported input operation
through the standard
codex-computer-use.exehelper; it does not introduce an alternate inputpath. With
transport.close()used at every exec boundary, a visible Notepad++ demonstrationused
press_key,click, andtype_text, and a human observer confirmed the animated screenborder and status pill on the physical display:
Codex is using your computer/Esc to. The installed helper binary contains those exact strings together with the border,cancel
status-pill, keyboard-hook, and overlay-rendering implementation. It also contains an explicit
exclude display overlay from capturespath, consistent with the overlay being visible on thephysical display but absent from Computer Use screenshots returned to the model. This verifies
that the workaround did not bypass the supported active-control transparency cue. We do not
claim that cue is an OS-level security boundary or that it signals every passive capture. The
official Computer Use documentation confirms the
foreground behaviour — Computer Use "runs on the active desktop", and users should "expect
ChatGPT to move the pointer, type, and take over the foreground". It does not currently
describe the overlay cue, so that part was verified against the shipped binary and direct
observation rather than the docs.
6. Suggested fixes
helper→kernel callbacks resolve against the current
activeExecIdrather than theoriginating one.
transport.close()works but is reached through aninternal property. A supported
sky.reset()would make the workaround legitimate.The separate
@oai/skypackage-exports defect tracked in #27287 remains relevant to otherComputer Use bootstrap failures, but is not part of this root cause.
7. Workaround for users today
Preserves
globalThis, imports, and REPL state. Heavier fallback if that ever fails:js_reset→ import + select + act + capture in one call (notejs_resetclearsglobalThis).transportis currently an internal property, so this remains an unsupported workaround eventhough it is materially lighter than resetting the kernel.
8. Also worth correcting
sky.documentation(), which the bundledSKILL.mdinstructs the model to call, does notexist in
@oai/sky0.6.2 — zero occurrences indist/. It throwssky.documentation is not a function, and a model left without an API reference then guessesparameter shapes, producing the misleading
window.app must be a non-empty string and window.id must be an integer >= 0. The real docsship on disk at
@oai/sky/docs/sky-window2-api.mdand in the plugin'sdocs/.9. Copy-ready Codex guidance and independent verification
This workaround does not patch the binaries. It teaches Codex to recreate the affected helper
transport at each Node REPL exec boundary. Per OpenAI's
AGENTS.mddocumentation, put reusable
global guidance in
~/.codex/AGENTS.md(%USERPROFILE%\.codex\AGENTS.mdon Windows) and starta new Codex run/session after editing it.
<details>
<summary>Drop-in <code>AGENTS.md</code> block</summary>
````markdown
Computer Use on Windows: refresh the exec-bound helper
Initialize Sky once per fresh
node_replkernel:Before Computer Use work in every new
node_replJS call, recreate the helper transport:Then list/select/act/capture normally in that same call. Multiple Computer Use operations
inside one JS call may share the transport and do not need intermediate closes.
Pass
Windowobjects verbatim as returned bysky.list_apps()orsky.list_windows().Never rebuild a window object by hand, and do not convert its integer
idto a string.If transport recreation fails, use the heavier fallback:
js_reset, re-import@oai/sky,then list, select, act, and capture within one JS call.
js_resetclearsglobalThis.sky.transportis currently internal API; revalidate this workaround after Codex, theComputer Use plugin, or
@oai/skyupdates.In
@oai/sky0.6.2,sky.documentation()is absent. Read the installed docs from dynamicallydiscovered paths rather than hardcoding version/hash directories:
%LOCALAPPDATA%\OpenAI\Codex\runtimes\cua_node\*\bin\node_modules\@oai\sky\docs\%USERPROFILE%\.codex\plugins\cache\openai-bundled\computer-use\*\docs\````
</details>
Verification on another affected installation:
AGENTS.mdis loaded.list_apps(),select exactly one returned non-sensitive test window, and capture text-only state with
get_window_state({window, include_screenshot:false, include_text:true}).returned
Windowobject.js_reset. As an optional control on anaffected build, omitting
transport.close()from the second call reproducesnode_repl exec context not found; adding it in the following call recovers.Two practical notes for implementers:
transport.close()on a kernel where no helper has spawned yet is a no-op, not anerror —
close()returns immediately when#childisnull(see §3). So the guarded call issafe to run unconditionally at the top of every JS exec, including the first.
include_text: truereturns whatever is onscreen, including secrets in an open editor buffer. During our own reproduction, an
unpredictable
Ctrl+Tablanded on a config file and the accessibility tree surfaced acredential-like value. Anything written back through
nodeReplpersists in plaintext in thesession transcript under
~/.codex/sessions/and is sent as model context. Use a window withno sensitive content, avoid unpredictable navigation mid-capture, and filter
document_textrather than dumping it wholesale.
This is sufficient to replicate the practical workaround. The process-count durability probe
in §5 is additional validation, not a required setup step.
---
Method and provenance
This analysis was produced by two AI models working in parallel on the affected machine,
coordinating directly through a shared file-backed message queue. Each had tools the other
lacked, and the split was load-bearing rather than cosmetic.
Claude Opus 5 supplied the static, external, and issue-research lane. It extracted both
node_repl.exeguard paths behind the shared error string; deobfuscated the Sky singleton andthe helper transport's
close()/ lazy-respawn behavior; captured live exec registrations,their short lifetimes, kernel PIDs, and the supervisor→kernel→helper process topology; mapped
those findings against #37281, #37180, and the separate package-exports issue; and designed
falsifiable discriminator tests. After the runtime finding, that transport deobfuscation
supplied the missing mechanism:
close()cleans up and nulls#child, and the next requestspawns a helper whose async resources belong to the current exec. It also audited the report
itself: independently verifying versions, citations, and the overlay strings in the shipped
helper binary, qualifying an unsupported callback-specific claim, and identifying the redaction
and first-exec no-op guidance needed for a safe public recipe.
GPT 5.6 Sol (Codex) supplied the live-runtime and operational lane. Codex executed and
timestamped the experiment matrix: plain-JS survival, repeated lightweight Sky calls,
same-exec versus cross-exec state captures, window rehydration, singleton re-import, reset
semantics, and active-exec registry inspection. Codex found the decisive lower-level escape
hatch empirically: close
sky.transport, then capture state in the same new exec. It verifiedthe alternating close→success / reuse→failure behavior, ran 12 successful close/respawn cycles
without helper-process accumulation, corrected the app-package/plugin version conflation, and
turned the finding into durable
AGENTS.mdguidance, a fallback path, an independentverification procedure, and the active-control overlay sanity check above.
The correction record remains important. Claude initially attributed the root cause to the
client singleton and advised Codex not to spend a cycle testing
close(); Codex tested thelower-level transport anyway, disproving the first explanation and finding the practical
workaround. The singleton analysis remained useful—it explains why re-importing cannot
recover—but it was demoted from cause to contributing constraint. In the other direction,
Claude's static follow-through converted an empirical workaround into a concrete lifecycle
mechanism, and its adversarial review caught overclaiming and an operational privacy hazard
before publication. Codex's experiments likewise corrected its own earlier blanket model that
the “second Sky call” always fails by showing that lightweight methods survive.
Neither evidence lane would have produced this report as written. The runtime experiments
established what works and falsified plausible alternatives; the static and external evidence
explained why it works, separated two identical error strings, and made the result actionable
for a maintainer. We include the collaboration history as provenance, not as a substitute for
the technical evidence above.
Confirmed on another affected Windows installation with the bundled Computer Use plugin 26.803.41515. Target application: Android Studio (studio64.exe).
Reproduction matches this issue:
I also independently tested the workaround from the comment above:
Calling it at the start of a new JS exec removes the exec-context error. The text-only state request then completes (Android Studio returned no accessibility tree on this machine). A screenshot-backed request advances past the original context error but then fails with a separate Windows capture error:
So the transport-close workaround is confirmed on plugin 26.803.41515, although this installation still cannot capture Android Studio because of the subsequent Windows Graphics Capture failure. This may overlap with #37629.
Confirmed the transport-close workaround on another affected installation.
Environment:
After a full Codex restart alone, a text-only get_window_state call had still failed with
node_repl exec context not found. In a new controlled run, I selected a newly created blank Notepad window from the verbatim list_windows result. At the start of the next node_repl execution I called:The single subsequent get_window_state({ include_screenshot: false, include_text: true }) call completed successfully. It returned a WindowState and did not reproduce the exec-context error. The blank Notepad target returned accessibility=null and zero screenshots, so this confirms removal of the context error but does not claim accessibility coverage for every app.
No activation, click, keyboard, typing, scrolling, screenshot capture, binary patch, runtime modification, or helper bypass was used. The transport was closed again after the test.
This looks like the same defect as #37013, and it no longer reproduces here.
@oai/sky: 0.6.6 (was 0.6.2;helper_transport.jsSHA-256 changed from6423BA83...to7BC54C5B...)With a fresh JS kernel,
get_window_state()called from anode_repl/jsexecution after the one that produced the window handle now succeeds. A screenshot id created in one call is also still valid forsky.click()in a later independent call, so the observe-then-act workflow works end to end.Full test details in #37013.