{"record":{"id":"bf98c69dc00184da","repo":"FuelLabs/sway","slug":"could-not-get-plugin-description","errorCode":null,"errorMessage":"Could not get plugin description.","messagePattern":"Could not get plugin description\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"forc/src/cli/commands/plugins.rs","lineNumber":95,"sourceCode":"            for path in plugin.1 {\n                println_warning(&format!(\"   {}\", path.display()));\n            }\n        }\n    }\n    Ok(())\n}\n\n/// Find a plugin's description\n///\n/// Given a canonical plugin path, returns the description included in the `-h` opt.\n/// Returns a generic description if a description cannot be found\nfn parse_description_for_plugin(plugin: &Path) -> String {\n    use std::process::Command;\n    let default_description = \"No description found for this plugin.\";\n    let proc = Command::new(plugin)\n        .arg(\"-h\")\n        .output()\n        .expect(\"Could not get plugin description.\");\n\n    let stdout = String::from_utf8_lossy(&proc.stdout);\n\n    // If the plugin doesn't support a -h flag\n    match stdout.split('\\n').nth(1) {\n        Some(x) => {\n            if x.is_empty() {\n                default_description.to_owned()\n            } else {\n                x.to_owned()\n            }\n        }\n        None => default_description.to_owned(),\n    }\n}\n\n/// # Panics\n///","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/FuelLabs/sway/blob/47e5e902faa42baf652dd6a0c88cd23390c1a614/forc/src/cli/commands/plugins.rs#L77-L113","documentation":"`forc plugins` enumerates executables named forc-* on PATH and, for each, runs `<plugin> -h` to extract the second stdout line as its description (parse_description_for_plugin). format_print_description invokes this for every discovered plugin even without --describe. This expect panics when the plugin process cannot be spawned at all — the binary exists on PATH but is not runnable.","triggerScenarios":"A PATH directory contains a forc-* file without the executable bit; a broken shebang pointing at a missing interpreter; a plugin binary built for a different OS/architecture; permission denied (noexec mount, ACL). Running `forc plugins` then panics while probing the first broken entry.","commonSituations":"Hand-copied plugin binaries (scp without +x); nix/store or network-mounted PATH entries with dangling symlinks; multi-arch dev machines mixing macOS and Linux plugin builds; leftover forc-* artifacts from interrupted installs.","solutions":["Locate the offending entry: `IFS=:; for d in $PATH; do ls -la \"$d\"/forc-* 2>/dev/null; done` and inspect for non-executable or broken files.","Fix or remove it: `chmod +x <path>/forc-xyz` if legitimate, otherwise delete the stale file.","Reinstall the plugin through fuelup/cargo so a valid executable lands on PATH."],"exampleFix":"# before\n$ chmod -x ~/.local/bin/forc-explore\n$ forc plugins\nthread 'main' panicked: Could not get plugin description.\n# after\n$ chmod +x ~/.local/bin/forc-explore\n$ forc plugins   # lists plugins","handlingStrategy":"validation","validationCode":"# verify every forc-* on PATH is executable and runs -h before listing\nIFS=:\nfor d in $PATH; do\n  for p in \"$d\"/forc-*; do\n    [ -e \"$p\" ] || continue\n    [ -x \"$p\" ] || { echo \"not executable: $p\" >&2; exit 1; }\n    \"$p\" -h >/dev/null 2>&1 || { echo \"cannot run: $p\" >&2; exit 1; }\n  done\ndone","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Install plugins via fuelup/cargo install instead of copying binaries by hand.","After copying a plugin across machines, chmod +x and run `<plugin> -h` once.","Keep personal bin dirs clean of leftover forc-* artifacts from interrupted installs."],"tags":["rust","forc","plugins","path","permissions","panic","process-spawn"],"backgroundTag":null,"analyzedSha":"47e5e902faa42baf652dd6a0c88cd23390c1a614","analyzedAt":"2026-08-16T07:57:45.555Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}