{"record":{"id":"3f3249416a3af50a","repo":"BigPizzaV3/CodexPlusPlus","slug":"native-browser-compatibility-is-still-enabled","errorCode":null,"errorMessage":"Native browser compatibility is still enabled","messagePattern":"Native browser compatibility is still enabled","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/native_browser.rs","lineNumber":699,"sourceCode":"        schema: 1,\n        generation: generation.into(),\n        state: state.into(),\n    })?;\n    file.seek(SeekFrom::Start(0))?;\n    file.set_len(0)?;\n    file.write_all(&bytes)?;\n    file.sync_all()?;\n    Ok(())\n}\n\nfn verify_restored_state(paths: &BrowserPaths) -> Result<()> {\n    if !paths.state_root.exists() {\n        return Ok(());\n    }\n    let control = paths.state_root.join(\"control.json\");\n    if control.exists() {\n        let value: Value = serde_json::from_slice(&read_regular(&control, 1024)?)?;\n        ensure!(\n            value[\"schema\"] == 1 && value[\"requireIdentification\"] == false,\n            \"Native browser compatibility is still enabled\"\n        );\n    }\n    for entry in fs::read_dir(&paths.state_root)? {\n        let key = entry?.file_name().to_string_lossy().to_string();\n        if !key_valid(&key) || !paths.state_root.join(&key).join(\"journal.json\").exists() {\n            continue;\n        }\n        let target = paths.runtime_root.join(&key).join(SERVICE);\n        if target.exists() {\n            let (_, original, _) = recovery_material(paths, &key, &RuntimeContract::pinned())?;\n            ensure!(\n                read_regular(&target, MAX_SERVICE)? == original,\n                \"Native browser service has not been restored\"\n            );\n        }\n    }","sourceCodeStart":681,"sourceCodeEnd":717,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/crates/codex-plus-core/src/native_browser.rs#L681-L717","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: shutdown verification sees stale enabled control\nlet _ = monitor.stop().await; // verify_restored_state -> \"still enabled\"\n\n// after: explicitly disable and flush state before stopping the monitor\nreconcile(&paths, false)?;\nmonitor.stop().await?;","handlingStrategy":"try-catch","validationCode":"// Pre-check the control marker before shutting down the monitor\nfn control_is_disabled(paths: &BrowserPaths) -> std::io::Result<bool> {\n    let p = paths.state_root.join(\"control.json\");\n    if !p.exists() { return Ok(true); }\n    let v: serde_json::Value = serde_json::from_slice(&std::fs::read(p)?)?;\n    Ok(v[\"schema\"] == 1 && v[\"requireIdentification\"] == false)\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = monitor.stop_and_verify().await {\n    if e.to_string().contains(\"still enabled\") {\n        // explicitly disable (rewrites control.json) then re-verify\n        reconcile(&paths, false)?;\n    }\n}","preventionTips":["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"],"tags":["state-verification","control-file","invalid-state","shutdown"],"backgroundTag":"invalid-state-transition","analyzedSha":"b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6","analyzedAt":"2026-09-19T23:35:21.129Z","contentChangedAt":"2026-09-19T23:35:21.129Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}