BigPizzaV3/CodexPlusPlus · error
Native browser compatibility is still enabled
Error message
Native browser compatibility is still enabled
What it means
verify_restored_state confirms that after the monitor has been shut down and compatibility disabled, the feature is really off. It reads state_root/control.json and requires schema==1 and requireIdentification==false; if control.json still says requireIdentification==true, native browser compatibility is still flagged as enabled and this error is thrown. This is a fail-closed post-condition check guarding against a shutdown path that skipped writing the disabled control marker.
Solutions
- Run reconcile(&paths, false) to explicitly disable: it rewrites control.json to {"schema":1,"requireIdentification":false} and restores the service, then restart the monitor if needed.
- Delete or fix the stale control.json in state_root (or restore the correct disabled marker) if it was hand-edited or came from an old backup, then re-verify.
- Ensure only one launcher/monitor instance owns the state (check monitor.lock/owner.lock) so a concurrent process is not re-enabling the flag during shutdown.
Example fix
// before: shutdown verification sees stale enabled control let _ = monitor.stop().await; // verify_restored_state -> "still enabled" // after: explicitly disable and flush state before stopping the monitor reconcile(&paths, false)?; monitor.stop().await?;
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check the control marker before shutting down the monitor
fn control_is_disabled(paths: &BrowserPaths) -> std::io::Result<bool> {
let p = paths.state_root.join("control.json");
if !p.exists() { return Ok(true); }
let v: serde_json::Value = serde_json::from_slice(&std::fs::read(p)?)?;
Ok(v["schema"] == 1 && v["requireIdentification"] == false)
} Try / catch
if let Err(e) = monitor.stop_and_verify().await {
if e.to_string().contains("still enabled") {
// explicitly disable (rewrites control.json) then re-verify
reconcile(&paths, false)?;
}
} Prevention
- Always call reconcile(paths, false) before stopping the monitor rather than relying on shutdown to flip state
- Never hand-edit control.json; treat it as library-owned state
- Ensure only one launcher owns the state (respect owner.lock/monitor.lock) to avoid concurrent re-enabling
- After version upgrades, run reconcile once to rewrite legacy control files to the current schema
When it happens
Trigger: wait_for_monitor_shutdown_at -> verify_restored_state while state_root/control.json exists with requireIdentification==true (or a malformed value that is not false). Happens when monitor shutdown occurred without reconcile_locked completing its disable branch, when a concurrent reconcile re-enabled the feature, or when control.json was hand-edited / written by an older version with a different schema.
Common situations: Killing or crashing the monitor before it wrote the disabled control.json; another launcher instance re-preparing the feature while shutdown verification runs; manually restoring an old state_root snapshot that still has the enabled control file; schema drift after a version upgrade.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- 微信连接已停止
- invalid built-in Dream Skin theme draft
- Native browser service has not been restored
- No DevTools target configured
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/3f3249416a3af50a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/native_browser.rs:699
schema: 1,
generation: generation.into(),
state: state.into(),
})?;
file.seek(SeekFrom::Start(0))?;
file.set_len(0)?;
file.write_all(&bytes)?;
file.sync_all()?;
Ok(())
}
fn verify_restored_state(paths: &BrowserPaths) -> Result<()> {
if !paths.state_root.exists() {
return Ok(());
}
let control = paths.state_root.join("control.json");
if control.exists() {
let value: Value = serde_json::from_slice(&read_regular(&control, 1024)?)?;
ensure!(
value["schema"] == 1 && value["requireIdentification"] == false,
"Native browser compatibility is still enabled"
);
}
for entry in fs::read_dir(&paths.state_root)? {
let key = entry?.file_name().to_string_lossy().to_string();
if !key_valid(&key) || !paths.state_root.join(&key).join("journal.json").exists() {
continue;
}
let target = paths.runtime_root.join(&key).join(SERVICE);
if target.exists() {
let (_, original, _) = recovery_material(paths, &key, &RuntimeContract::pinned())?;
ensure!(
read_regular(&target, MAX_SERVICE)? == original,
"Native browser service has not been restored"
);
}
}View on GitHub (pinned to b1ed92e5e4)