{"record":{"id":"5727be114a49c423","repo":"FuelLabs/sway","slug":"plugin-exit-status-unknown","errorCode":null,"errorMessage":"plugin exit status unknown","messagePattern":"plugin exit status unknown","errorType":"console","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"forc/src/cli/mod.rs","lineNumber":157,"sourceCode":"        Forc::Check(command) => check::exec(command),\n        Forc::Clean(command) => clean::exec(command),\n        Forc::Completions(command) => completions::exec(command),\n        Forc::Init(command) => init::exec(command),\n        Forc::New(command) => new::exec(command),\n        Forc::ParseBytecode(command) => parse_bytecode::exec(command),\n        Forc::Plugins(command) => plugins::exec(command),\n        Forc::Test(command) => test::exec(command),\n        Forc::Update(command) => update::exec(command),\n        Forc::Remove(command) => remove::exec(command),\n        Forc::Template(command) => template::exec(command),\n        Forc::ContractId(command) => contract_id::exec(command),\n        Forc::PredicateRoot(command) => predicate_root::exec(command),\n        Forc::Plugin(args) => {\n            let output = plugin::execute_external_subcommand(&args)?;\n            let code = output\n                .status\n                .code()\n                .ok_or_else(|| anyhow!(\"plugin exit status unknown\"))?;\n            std::process::exit(code);\n        }\n    }\n}\n","sourceCodeStart":139,"sourceCodeEnd":162,"githubUrl":"https://github.com/FuelLabs/sway/blob/47e5e902faa42baf652dd6a0c88cd23390c1a614/forc/src/cli/mod.rs#L139-L162","documentation":"When forc dispatches an unknown subcommand to an external plugin (forc-<args>), it runs the binary via plugin::execute_external_subcommand and then propagates the process's exit code with std::process::exit. ExitStatus::code() is None exactly when the process was terminated by a Unix signal rather than exiting normally, so forc cannot map it to an exit code and errors with \"plugin exit status unknown\".","triggerScenarios":"A forc plugin (forc-wallet, forc-fmt, etc.) crashing or being killed mid-run — SIGSEGV, SIGKILL (OOM killer), abort on panic with panic=abort — when invoked as `forc <plugin-subcommand>`.","commonSituations":"Plugin killed by the OOM killer, a segfault in a native plugin, Ctrl-C-related signals, or a plugin binary linked against incompatible shared libraries that aborts at startup.","solutions":["Run the plugin binary directly (forc-<name> <args>) to see the real signal/crash output without forc's wrapper","Reinstall/upgrade the plugin (fuelup or cargo install) to fix crashes or ABI mismatches","If killed by OOM, reduce memory pressure or the workload size and rerun"],"exampleFix":"# before\nforc fmt   # crashes with signal, forc reports exit status unknown\n\n# after\nforc-fmt      # run directly to observe the crash, then reinstall/upgrade it","handlingStrategy":"retry","validationCode":"// Smoke-test the plugin before letting forc dispatch to it.\nlet status = std::process::Command::new(\"forc-fmt\").arg(\"--help\").status()?;\nif !status.success() {\n    anyhow::bail!(\"forc-fmt is not healthy; reinstall before dispatching via forc\");\n}","typeGuard":null,"tryCatchPattern":"let output = std::process::Command::new(\"forc\").args(plugin_args).output()?;\nif output.status.code().is_none() {\n    // terminated by a signal: rerun the plugin directly to surface the crash\n    eprintln!(\"plugin killed by signal; retrying '{plugin_name}' directly\");\n    return run_plugin_directly(plugin_name, plugin_args);\n}","preventionTips":["Keep plugins and forc versions aligned via fuelup","Watch for OOM/segfault patterns in CI when plugins process large repositories; report reproducible crashes upstream"],"tags":["forc","plugin","signal","process-exit"],"backgroundTag":null,"analyzedSha":"47e5e902faa42baf652dd6a0c88cd23390c1a614","analyzedAt":"2026-08-16T07:57:45.555Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}