{"record":{"id":"07c438f9e4032e7f","repo":"BigPizzaV3/CodexPlusPlus","slug":"embedded-official-remote-plugin-marketplace-root-m","errorCode":null,"errorMessage":"embedded official remote plugin marketplace root mismatch","messagePattern":"embedded official remote plugin marketplace root mismatch","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/plugin_marketplace.rs","lineNumber":489,"sourceCode":"        }\n    }\n    (!relative.as_os_str().is_empty()).then_some(relative)\n}\n\nfn validate_openai_plugins_marketplace_root(root: &Path) -> anyhow::Result<()> {\n    let marketplace = local_openai_curated_marketplace_root_from_root(root)?\n        .ok_or_else(|| anyhow::anyhow!(\"downloaded openai/plugins marketplace is invalid\"))?;\n    if marketplace != root {\n        anyhow::bail!(\"downloaded openai/plugins marketplace root mismatch\");\n    }\n    Ok(())\n}\n\nfn validate_openai_curated_remote_marketplace_root(root: &Path) -> anyhow::Result<()> {\n    let marketplace = local_openai_curated_remote_marketplace_root_from_root(root)?\n        .ok_or_else(|| anyhow::anyhow!(\"embedded official remote plugin marketplace is invalid\"))?;\n    if marketplace != root {\n        anyhow::bail!(\"embedded official remote plugin marketplace root mismatch\");\n    }\n    Ok(())\n}\n\nfn local_openai_curated_marketplace_root_from_root(root: &Path) -> anyhow::Result<Option<PathBuf>> {\n    let marketplace_path = root\n        .join(\".agents\")\n        .join(\"plugins\")\n        .join(\"marketplace.json\");\n    if !marketplace_path.is_file() {\n        return Ok(None);\n    }\n    let text = std::fs::read_to_string(&marketplace_path)\n        .with_context(|| format!(\"failed to read {}\", marketplace_path.display()))?;\n    let marketplace: serde_json::Value = serde_json::from_str(&text)\n        .with_context(|| format!(\"failed to parse {}\", marketplace_path.display()))?;\n    if marketplace.get(\"name\").and_then(serde_json::Value::as_str)\n        != Some(OPENAI_CURATED_MARKETPLACE)","sourceCodeStart":471,"sourceCodeEnd":507,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/1f431ae49b57b3055e0e6845ba6156c6b4232b4d/crates/codex-plus-core/src/plugin_marketplace.rs#L471-L507","documentation":"Thrown by validate_openai_curated_remote_marketplace_root in crates/codex-plus-core/src/plugin_marketplace.rs when validating the layout of the embedded official remote plugin marketplace after extraction. The validator locates the directory containing .agents/plugins/marketplace.json whose name field equals OPENAI_CURATED_REMOTE_MARKETPLACE and whose plugins array is non-empty with a sibling plugins/ directory, then requires that directory to be exactly the expected root. A mismatch means the extracted payload's on-disk layout does not line up with the root the validator was given (e.g. the zip nests content one level deeper, or the marketplace.json landed in a parent/child directory instead of the root).","triggerScenarios":"Bootstrapping or re-extracting the embedded official remote plugin marketplace when the bundled zip's internal layout changed; a build that packaged the marketplace under a subfolder so .agents/plugins/marketplace.json resolves to a different directory than root; calling validate_openai_curated_remote_marketplace_root with a root that is a parent of the actual marketplace directory.","commonSituations":"Upgrading the crate to a version whose embedded marketplace zip was repackaged with a different directory structure; a corrupted or partially-extracted marketplace cache left over from a previous run; manual edits to ~/.agents/plugins/marketplace.json that renamed or moved the marketplace root.","solutions":["Delete the extracted marketplace directory and let the tool re-extract the embedded zip from scratch so the layout matches the validator's expectation","Verify the embedded zip actually places .agents/plugins/marketplace.json at the archive root (not nested under an extra folder) and fix the packaging if it does not","Check that marketplace.json has name == the OPENAI_CURATED_REMOTE_MARKETPLACE constant, a non-empty plugins array, and that a plugins/ directory sits next to .agents/","If you pass a custom root, make sure it is the directory that directly contains .agents/, not an ancestor or child of it"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"fn marketplace_layout_ok(root: &Path) -> bool {\n    let mp = root.join(\".agents\").join(\"plugins\").join(\"marketplace.json\");\n    mp.is_file() && root.join(\"plugins\").is_dir()\n}","typeGuard":null,"tryCatchPattern":"match install_embedded_remote_marketplace(root) {\n    Ok(()) => {}\n    Err(e) if e.to_string().contains(\"marketplace root mismatch\") => {\n        let _ = std::fs::remove_dir_all(root);\n        install_embedded_remote_marketplace(root)?; // clean re-extract\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never hand-move .agents/plugins/marketplace.json out of the marketplace root","Treat the extracted marketplace directory as tool-managed: edit plugin entries via the manager, not the filesystem","After upgrading the app, let it re-extract the embedded marketplace instead of preserving the old directory"],"tags":["plugin-marketplace","integrity-check","embedded-resources","filesystem-layout"],"backgroundTag":"resource-integrity-check-failed","analyzedSha":"1f431ae49b57b3055e0e6845ba6156c6b4232b4d","analyzedAt":"2026-08-16T20:54:18.598Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}