{"record":{"id":"4d92cba0c8b63aff","repo":"BigPizzaV3/CodexPlusPlus","slug":"embedded-official-remote-plugin-marketplace-is-inv","errorCode":null,"errorMessage":"embedded official remote plugin marketplace is invalid","messagePattern":"embedded official remote plugin marketplace is invalid","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/plugin_marketplace.rs","lineNumber":487,"sourceCode":"            Component::CurDir => {}\n            _ => return None,\n        }\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()))?;","sourceCodeStart":469,"sourceCodeEnd":505,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/1f431ae49b57b3055e0e6845ba6156c6b4232b4d/crates/codex-plus-core/src/plugin_marketplace.rs#L469-L505","documentation":"validate_openai_curated_remote_marketplace_root (crates/codex-plus-core/src/plugin_marketplace.rs:484) applies the same manifest contract to the embedded remote marketplace asset: local_openai_curated_remote_marketplace_root_from_root must find .agents/plugins/marketplace.json whose name equals OPENAI_CURATED_REMOTE_MARKETPLACE, a non-empty plugins array, and a plugins/ directory. A None result bails with 'embedded official remote plugin marketplace is invalid'. Because the asset ships inside the binary, this error signals a broken build/embed step or a corrupted extraction — not a network problem.","triggerScenarios":"Building or running with an embedded remote-marketplace asset that fails validation: the include/asset copy step shipped a stale, empty, or wrong-named manifest; the build embedded the curated (non-remote) marketplace by mistake; or runtime extraction of the embedded tree was incomplete.","commonSituations":"CI builds where the asset-fetch step silently failed and an empty directory got embedded; version skew after the remote marketplace `name` field changed but the constant OPENAI_CURATED_REMOTE_MARKETPLACE was not updated; forks regenerating assets with a different tool that drops the plugins/ dir; tampering with the embedded asset path at rest.","solutions":["Regenerate/re-copy the embedded asset and rebuild: ensure the source tree for the remote marketplace contains .agents/plugins/marketplace.json with name == OPENAI_CURATED_REMOTE_MARKETPLACE, non-empty plugins[], and a plugins/ dir","Diff the constant vs the manifest: plugin_marketplace.rs's OPENAI_CURATED_REMOTE_MARKETPLACE must equal the asset's name field exactly after any upstream rename","Run the crate's existing tests around the embedded marketplace (cargo test -p codex-plus-core plugin_marketplace) to catch embed breakage in CI before release","If the runtime-extracted copy is corrupted on disk, clear the extracted cache location so it re-extracts from the binary"],"exampleFix":"# before: build embeds the wrong (curated) asset\nassets/plugins/marketplace.json  # name: \"openai\" (curated constant)\n# constant expects name: \"openai-remote-plugins\" -> invalid\n\n# after: embed the remote variant\nassets/plugins/marketplace.json  # name matches OPENAI_CURATED_REMOTE_MARKETPLACE\n# plus assets/plugins/ with at least one plugin dir","handlingStrategy":"validation","validationCode":"// Build-time check: assert the embedded asset passes validation before shipping\n#[test]\nfn embedded_remote_marketplace_valid() {\n    let dir = extract_embedded_remote_marketplace_to_temp();\n    assert!(validate_openai_curated_remote_marketplace_root(&dir).is_ok(),\n        \"embedded asset must ship a valid manifest\");\n}","typeGuard":"fn embedded_manifest_matches(value: &serde_json::Value, constant: &str) -> bool {\n    value.get(\"name\").and_then(|n| n.as_str()) == Some(constant)\n        && value.get(\"plugins\").and_then(|p| p.as_array()).is_some_and(|a| !a.is_empty())\n}","tryCatchPattern":"if let Err(e) = validate_openai_curated_remote_marketplace_root(&root) {\n    if e.to_string().contains(\"embedded official remote plugin marketplace is invalid\") {\n        // asset/build problem: fail loudly in CI, degrade at runtime\n        tracing::error!(\"embedded marketplace asset failed validation; rebuild required\");\n    }\n    return Err(e);\n}","preventionTips":["Gate releases on the embedded-asset validation test so broken embeds never ship","Keep OPENAI_CURATED_REMOTE_MARKETPLACE in lockstep with the asset's `name` field","Regenerate embedded assets via the canonical build step only; never hand-edit them","Clear extracted asset caches after upgrades so corrupted extractions re-materialize"],"tags":["rust","plugin-marketplace","embedded-asset","validation","build-integrity"],"backgroundTag":"embedded-asset-invalid","analyzedSha":"1f431ae49b57b3055e0e6845ba6156c6b4232b4d","analyzedAt":"2026-08-16T20:54:18.598Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}