{"record":{"id":"3c282e8389e0aa62","repo":"FuelLabs/sway","slug":"failed-to-run-forc-plugins","errorCode":null,"errorMessage":"Failed to run forc plugins","messagePattern":"Failed to run forc plugins","errorType":"console","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"scripts/mdbook-forc-documenter/src/plugins.rs","lineNumber":16,"sourceCode":"use anyhow::{anyhow, Result};\nuse std::{collections::HashSet, process};\n\n/// Detects plugins available via `PATH`.\n///\n/// Note that plugin discovery works reliably within the Sway CI since the installed plugins are in\n/// a controlled environment. Building the book locally on your own machine may create a different\n/// book depending on what plugins are available on your PATH.\npub(crate) fn forc_plugins_from_path() -> Result<Vec<String>> {\n    let output = process::Command::new(\"forc\")\n        .arg(\"plugins\")\n        .output()\n        .expect(\"Failed running forc plugins\");\n\n    if !output.status.success() {\n        return Err(anyhow!(\"Failed to run forc plugins\"));\n    }\n\n    let mut plugins = HashSet::new();\n    let s = String::from_utf8_lossy(&output.stdout) + String::from_utf8_lossy(&output.stderr);\n\n    for plugin in s.lines() {\n        if let Some((\"\", command)) = plugin.split_once(\"forc-\") {\n            plugins.insert(command.to_string());\n        }\n    }\n\n    Ok(Vec::from_iter(plugins))\n}\n","sourceCodeStart":1,"sourceCodeEnd":30,"githubUrl":"https://github.com/FuelLabs/sway/blob/47e5e902faa42baf652dd6a0c88cd23390c1a614/scripts/mdbook-forc-documenter/src/plugins.rs#L1-L30","documentation":"To document installed plugins, the preprocessor shells out to `forc plugins` and parses lines containing \"forc-\". After the child process runs, this anyhow error is returned when the process exits with a non-zero status. (A missing/unspawnable forc binary is a different failure: the .expect(\"Failed running forc plugins\") panic just above.) As the doc comment notes, discovery is only reliable in Sway CI where the plugin set is controlled.","triggerScenarios":"Running the docs build with an old forc on PATH that predates the `plugins` subcommand (unknown subcommand -> non-zero exit); a shell alias/wrapper named forc that fails; a corrupted fuelup-managed forc that exits non-zero; PATH pointing at a forc binary from an incompatible toolchain.","commonSituations":"Building the book on a developer machine whose fuelup default toolchain is outdated; CI images where forc was installed manually at an old version; local PATH ordering picking up a broken binary before the fuelup one.","solutions":["Update the toolchain so `forc plugins` succeeds in the same shell: `fuelup update && fuelup default latest`.","Verify before building: `which forc && forc plugins` must list plugins with exit code 0.","If you must keep an old forc, install a newer one side-by-side and prepend its bin dir to PATH only for the mdbook build."],"exampleFix":"// before\n$ forc plugins\nerror: unrecognized subcommand 'plugins'  -> preprocessor fails\n// after\n$ fuelup update && forc plugins\nforc-alerts, forc-explore, forc-fmt, forc-lsp, forc-tx  -> docs build proceeds","handlingStrategy":"validation","validationCode":"# before building docs, require a forc that supports `plugins`\ncommand -v forc >/dev/null 2>&1 || { echo \"forc not on PATH\" >&2; exit 1; }\nforc plugins >/dev/null 2>&1 || { echo \"forc plugins failed; run fuelup update\" >&2; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pin the fuelup toolchain in CI and update before docs jobs.","Smoke-test `forc plugins` in the same shell/environment that runs mdbook.","Check `which forc` resolves to the fuelup-managed binary, not a stale copy."],"tags":["rust","sway","forc","plugins","path","toolchain-version","docs"],"backgroundTag":null,"analyzedSha":"47e5e902faa42baf652dd6a0c88cd23390c1a614","analyzedAt":"2026-08-16T07:57:45.555Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}