You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Computer Use on Windows: get_window_state fails with node_repl exec context not found #37281
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 @Computer and ask it to inspect/control that app.
Initialize @oai/sky through the bundled node_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 }), or
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.requestMeta exists, 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.
Root cause and workaround: the Computer Use helper transport is bound to the exec context that spawned it
If you only want the fix: call await sky.transport.close() at the start of every new node_repl JS call, before any Computer Use work. No js_reset needed. Copy-ready AGENTS.md block in §9; everything else is why it happens.
1. Summary
node_repl exec context not found on Computer Use calls is caused by the persistent helper
transport outliving the AsyncLocalStorage exec context in which it was created.
The transport holds a handle to a long-lived codex-computer-use.exe child process. That
process 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 that
originating exec. From any later exec, execState.id !== activeExecId and 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 new
JS call. js_reset is not required.
2. Environment
Codex app package 26.803.5235.0, Computer Use plugin 26.803.41515
Independently 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:
functiongetCurrentExecState(){constexecState=getAsyncExecState();// AsyncLocalStorage preserves the originating store for late callbacks, even// after the surrounding exec has already finished. Most helpers still require// an active exec because their results attach to the current tool call.if(execState.id!==activeExecId)thrownewError("node_repl exec context not found");returnexecState;}
The transport, from @oai/sky/dist/.../windows/internal/helper_transport.js (deobfuscated):
close(){constproc=this.#child;if(proc==null)returnPromise.resolve();if(proc.exitCode!=null||proc.signalCode!=null){this.#cleanup(proc);returnPromise.resolve();}returnthis.request("close",{}).catch(()=>proc.kill()).finally(()=>this.#cleanup(proc));}// #cleanup nulls #childrequest(method,params,opts={}){letproc=this.#child ??this.#spawnHelper();// <-- lazy respawn when #child is nullthis.#child =proc;// ... respawn again if the process has since exited ...returnthis.#send(proc,method,params,turnMeta,opts.createElicitation);}
close() nulls #child; the next request() spawns a fresh helper inside the current
exec, 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() and get_window() behaved as request/response operations and survived across execs. get_window_state() exercised the failing path — note createElicitation threaded through
every request(), and the string failed to reply to node_repl emit_image request in node_repl.exe. The evidence supports a helper→kernel callback as the discriminator, although
it does not yet isolate whether elicitation, image emission, or another callback is responsible.
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:
Kernel itself is healthy across calls: after js_reset, list_apps() succeeded at
22:12:32.236, and a following separate call containing only 1 + 1 returned 2 at
22:12:36.532.
Not all Sky methods fail: three separate list_apps() calls across distinct execs all
succeeded (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 context
error. Two get_window_state() calls inside one exec both succeeded
(22:14:27.318–22:14:27.711).
Failure is immediate, which rules out a waiting-based timeout/GC recovery explanation.
Rehydration is not a fix: get_window({id, app}) succeeded at 22:14:06.992, and get_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_reset clears globalThis ({"typeofSky":"undefined","hasOwnSky":false}), so re-import
is mandatory with that approach.
Decisive: baseline capture succeeded 22:19:16.702. Next exec: await sky.transport.close() then get_window_state() → succeeded 22:19:21.762 with no js_reset. Reusing that new transport in the following exec failed again. Closing again
recovered at 22:19:34.821.
Follow-up durability probe: 12 consecutive, separate JS execs each ran transport.close() followed by a text-only get_window_state() against the same returned
Notepad++ window. All 12 succeeded. No codex-computer-use.exe process existed before the
run, 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 a
callback-free state path: the API rejects it with get_window_state must request include_text, include_screenshot, or both.
Static / external (Claude):
Exec registrations in ~/.codex/node_repl/active_execs/ live ~1 second, fresh UUID per
JS call, e.g. {"execId":"b625ec45-...","nodeReplPid":19300,"kernelPid":10452,...}.
Process topology: 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, 778
bytes: let n = null; ... return n || (n = create_client(...))). This is why re-import does
not 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.exe helper; it does not introduce an alternate input
path. With transport.close() used at every exec boundary, a visible Notepad++ demonstration
used press_key, click, and type_text, and a human observer confirmed the animated screen
border and status pill on the physical display: Codex is using your computer / Esc to cancel. The installed helper binary contains those exact strings together with the border,
status-pill, keyboard-hook, and overlay-rendering implementation. It also contains an explicit exclude display overlay from captures path, consistent with the overlay being visible on the
physical 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
Recreate or rebind the helper transport per exec. Either spawn per exec, or have
helper→kernel callbacks resolve against the current activeExecId rather than the
originating one.
Expose the escape hatch officially.transport.close() works but is reached through an
internal property. A supported sky.reset() would make the workaround legitimate.
The separate @oai/sky package-exports defect tracked in #27287 remains relevant to other
Computer Use bootstrap failures, but is not part of this root cause.
7. Workaround for users today
// Before Computer Use work in each NEW JS call, once Sky has been imported:if(globalThis.sky?.transport?.close){awaitsky.transport.close();}// Then list / select / act / capture normally. Multiple operations in this call are fine.
Preserves globalThis, imports, and REPL state. Heavier fallback if that ever fails: js_reset → import + select + act + capture in one call (note js_reset clears globalThis). transport is currently an internal property, so this remains an unsupported workaround even
though it is materially lighter than resetting the kernel.
8. Also worth correcting
sky.documentation(), which the bundled SKILL.md instructs the model to call, does not
exist in @oai/sky 0.6.2 — zero occurrences in dist/. It throws sky.documentation is not a function, and a model left without an API reference then guesses
parameter shapes, producing the misleading window.app must be a non-empty string and window.id must be an integer >= 0. The real docs
ship on disk at @oai/sky/docs/sky-window2-api.md and in the plugin's docs/.
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.md
documentation, put reusable
global guidance in ~/.codex/AGENTS.md (%USERPROFILE%\.codex\AGENTS.md on Windows) and start
a new Codex run/session after editing it.
Drop-in AGENTS.md block
## Computer Use on Windows: refresh the exec-bound helper
Initialize Sky once per fresh `node_repl` kernel:
```jsif (!globalThis.sky) {
const { sky } =awaitimport("@oai/sky");
globalThis.sky= sky;
}
```
Before Computer Use work in every **new**`node_repl` JS call, recreate the helper transport:
```jsif (globalThis.sky?.transport?.close) {
awaitsky.transport.close();
}
```Then list/select/act/capture normally in that same call. Multiple Computer Use operationsinside one JS call may share the transport and do not need intermediate closes.Pass `Window` objects verbatim as returned by `sky.list_apps()` or `sky.list_windows()`.Never rebuild a window object by hand, and do not convert its integer `id` to 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_reset` clears `globalThis`.`sky.transport` is currently internal API; revalidate this workaround after Codex, theComputer Use plugin, or `@oai/sky` updates.In `@oai/sky` 0.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\`
Verification on another affected installation:
Start a new Codex run/session so the global AGENTS.md is loaded.
In one Node REPL call, import Sky, close the transport if present, call 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}).
In a second Node REPL call, close the transport and repeat state capture using that same
returned Window object.
Expected result: both captures succeed without js_reset. As an optional control on an
affected build, omitting transport.close() from the second call reproduces node_repl exec context not found; adding it in the following call recovers.
Two practical notes for implementers:
Calling transport.close() on a kernel where no helper has spawned yet is a no-op, not an
error — close() returns immediately when #child is null (see §3). So the guarded call is
safe to run unconditionally at the top of every JS exec, including the first.
Redact before writing accessibility output.include_text: true returns whatever is on
screen, including secrets in an open editor buffer. During our own reproduction, an
unpredictable Ctrl+Tab landed on a config file and the accessibility tree surfaced a
credential-like value. Anything written back through nodeRepl persists in plaintext in the
session transcript under ~/.codex/sessions/ and is sent as model context. Use a window with
no sensitive content, avoid unpredictable navigation mid-capture, and filter document_text
rather 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.exe guard paths behind the shared error string; deobfuscated the Sky singleton and
the 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 request
spawns 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 verified
the 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.md guidance, a fallback path, an independent
verification 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 the
lower-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:
sky.list_apps() discovers exactly one Android Studio window.
Without the workaround, both text-only and screenshot-backed sky.get_window_state() fail with: Error: node_repl exec context not found.
Reinstalling the plugin, restarting the desktop app, refreshing the returned window, and retrying do not fix it.
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:
IGraphicsCaptureItemInterop.CreateForMonitor failed: The specified service does not exist as an installed service. (0x80070424)
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:
Codex Desktop 26.803.5235.0
Computer Use plugin 26.803.41515
@oai/sky 0.6.2
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.
Codex Desktop AppX: 26.803.10989.0 x64
Computer Use plugin: 26.803.81509
@oai/sky: 0.6.6 (was 0.6.2; helper_transport.js SHA-256 changed from 6423BA83... to 7BC54C5B...)
Windows 10.0.26200 x64, stock install (extracted runtime matches the AppX copy byte for byte)
With a fresh JS kernel, get_window_state() called from a node_repl/js execution after the one that produced the window handle now succeeds. A screenshot id created in one call is also still valid for sky.click() in a later independent call, so the observe-then-act workflow works end to end.
Activity
github-actions commentedon Aug 6, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
node_repl exec context not found#37180Powered by Codex Action
KEYLEDGER commentedon Aug 8, 2026
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:
execState == nulllaunch_app, in the approval/elicitation callbackexecState.id !== activeExecIdThe 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 cancel. The installed helper binary contains those exact strings together with the border,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.
Drop-in
AGENTS.mdblockVerification 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.
zhivovmik-hash commentedon Aug 9, 2026
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.
rayb-b commentedon Aug 10, 2026
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.
jiangyuShiro commentedon Aug 11, 2026
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.