BigPizzaV3/CodexPlusPlus · error
Unexpected native runtime layout
Error message
Unexpected native runtime layout
What it means
selected_key validates a discovered native CUA runtime descriptor by checking that the configured node command sits at a fixed layout relative to the runtime cache root: exactly 3 path components (<runtime-key>/bin/node.exe). This error is thrown when the node command, relative to the runtime cache root, does not decompose into exactly 3 components — i.e. the executable lives in a nested or flat directory this library does not recognize.
Solutions
- Point mcpServers.cua_repl.command back at <runtime-root>/<key>/bin/node.exe for a runtime inside the cache root.
- Verify the runtime cache root is correct (LOCALAPPDATA/OpenAI/Codex/runtimes/cua_node) and that discover is called with the same root that produced the descriptor.
- Reinstall/repair the native CUA runtime so it regenerates the expected <key>/bin/node.exe layout.
- If a newer runtime intentionally changes layout, update the layout check (parts.len() == 3 and the bin/node.exe path) in native_browser.rs.
Example fix
// before: descriptor command points outside the expected layout "command": "D:/tools/node/node.exe" // after: command inside the runtime cache with key/bin/node.exe layout "command": "C:/Users/me/AppData/Local/OpenAI/Codex/runtimes/cua_node/rt-1/bin/node.exe"
Defensive patterns
Strategy: validation
Validate before calling
let node = PathBuf::from(descriptor["mcpServers"]["cua_repl"]["command"].as_str()?);
let rel = node.strip_prefix(&runtime_root)?;
if rel.components().count() != 3 {
eprintln!("runtime layout unexpected: {}", rel.display());
reinstall_runtime()?;
} Type guard
fn has_canonical_layout(node: &Path, root: &Path) -> bool {
node.strip_prefix(root)
.map(|rel| {
rel.components().count() == 3
&& rel.starts_with("bin")
&& rel.ends_with("node.exe")
})
.unwrap_or(false)
} Try / catch
match selected_key(&descriptor, &root) {
Ok(key) => use_runtime(key),
Err(e) if e.to_string().contains("Unexpected native runtime layout") => {
repair_or_reinstall_runtime()?;
}
Err(e) => return Err(e),
} Prevention
- Keep the runtime cache under the default LOCALAPPDATA path
- Never hand-edit the mcpServers.cua_repl command path
- Reinstall the runtime rather than moving/renaming its directories
- After moving caches, regenerate the descriptor instead of updating paths manually
When it happens
Trigger: discover() -> selected_key() on an MCP descriptor whose mcpServers.cua_repl.command points at a node binary not matching <root>/<key>/bin/node.exe: an unusual install layout, a custom node path in the descriptor, a moved or renamed runtime cache directory.
Common situations: User reinstalled Node/ Codex runtime into a custom location and hand-edited the descriptor; cache root passed to discover differs from the one used to write the descriptor (LOCALAPPDATA redirection, portable install); a runtime-cache migration changed the directory depth.
Related errors
- built-in Dream Skin theme cannot be deleted
- built-in Dream Skin theme is read-only
- Conflicting native Node selection
- current Dream Skin theme cannot be deleted
- Dream Skin theme name is empty
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/c0122eda68c53927.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/native_browser.rs:290
let path = serde_json::to_string(&control.to_str().context("Non-Unicode control path")?)?;
let replacement = format!(
"new nf(r,this.clientApi,()=>ze(this.runtime),this.turnEndedTracker,cppNativeIdentificationReader(this.runtime,cD,ze,{path}))"
);
Ok(format!("{}\n{HELPER}", text.replacen(ANCHOR, &replacement, 1)).into_bytes())
}
fn selected_key(descriptor: &Value, root: &Path) -> Result<String> {
let server = &descriptor["mcpServers"]["cua_repl"];
let node = PathBuf::from(
server["command"]
.as_str()
.context("Missing native Node command")?,
);
let relative = node
.strip_prefix(root)
.context("Native Node is outside the runtime cache")?;
let parts: Vec<_> = relative.components().collect();
ensure!(parts.len() == 3, "Unexpected native runtime layout");
let key = parts[0]
.as_os_str()
.to_str()
.context("Invalid runtime key")?;
ensure!(
key_valid(key) && relative == Path::new(key).join("bin/node.exe"),
"Unexpected native runtime layout"
);
let env = &server["env"];
ensure!(
env["NODE_REPL_NODE_PATH"].as_str().map(Path::new) == Some(node.as_path()),
"Conflicting native Node selection"
);
let worker = root.join(key).join("bin/node_repl.exe");
ensure!(
env["CUA_REPL_NODE_REPL_PATH"].as_str().map(Path::new) == Some(worker.as_path()),
"Conflicting native worker selection"
);View on GitHub (pinned to b1ed92e5e4)