{"record":{"id":"e76c07f1dc6a45ff","repo":"espanso/espanso","slug":"missing-cli-args-in-worker-main","errorCode":null,"errorMessage":"missing cli_args in worker main","messagePattern":"missing cli_args in worker main","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"espanso/src/cli/worker/mod.rs","lineNumber":66,"sourceCode":"pub fn new() -> CliModule {\n    #[allow(clippy::needless_update)]\n    CliModule {\n        requires_paths: true,\n        requires_config: true,\n        requires_linux_capabilities: true,\n        enable_logs: true,\n        log_mode: super::LogMode::AppendOnly,\n        subcommand: \"worker\".to_string(),\n        entry: worker_main,\n        ..Default::default()\n    }\n}\n\nfn worker_main(args: CliModuleArgs) -> i32 {\n    prevent_running_as_root_on_macos();\n\n    let paths = args.paths.expect(\"missing paths in worker main\");\n    let cli_args = args.cli_args.expect(\"missing cli_args in worker main\");\n\n    // When restarted, the daemon passes the reason why the worker was restarted (config_change, etc)\n    let start_reason = cli_args.value_of(\"start-reason\").map(String::from);\n    debug!(\"starting with start-reason = {start_reason:?}\");\n\n    // Avoid running multiple worker instances\n    let lock_file = acquire_worker_lock(&paths.runtime);\n    if lock_file.is_none() {\n        error!(\"worker is already running!\");\n        return WORKER_ALREADY_RUNNING;\n    }\n\n    let config_store = args\n        .config_store\n        .expect(\"missing config store in worker main\");\n    let match_store = args\n        .match_store\n        .expect(\"missing match store in worker main\");","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/espanso/espanso/blob/e6c3736675048026a057f1c4803d59242482fa7b/espanso/src/cli/worker/mod.rs#L48-L84","documentation":"Immediately after paths, worker_main does args.cli_args.expect(\"missing cli_args in worker main\"). The parsed clap arguments are attached by the dispatcher; the expect panics when cli_args was never populated. Like the missing-paths check, this is an internal contract violation of the CliModuleArgs wiring rather than a user-recoverable condition.","triggerScenarios":"worker_main called by the dispatch layer without first assigning args.cli_args from the parsed clap matches (wiring bug or custom entry point).","commonSituations":"Forked/patched builds with altered CLI dispatch; new subcommand plumbing that forgot to pass matches through; direct programmatic invocation of worker_main.","solutions":["Make the dispatcher assign args.cli_args from the parsed clap matches before calling worker_main.","Keep dispatch code in sync with the espanso version — re-apply local patches to the current dispatch flow.","Invoke espanso through its normal CLI entry point rather than calling worker_main directly.","Convert the expect into a clean error in custom builds."],"exampleFix":"// before\nlet cli_args = args.cli_args.expect(\"missing cli_args in worker main\");\n\n// after\nlet cli_args = args.cli_args.ok_or_else(|| anyhow::anyhow!(\n    \"missing cli_args in worker main: dispatcher did not pass parsed arguments\"\n))?;","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"fn require_cli_args(args: &CliModuleArgs) -> Result<&ArgMatches, String> {\n    args.cli_args.as_ref().ok_or_else(|| \"missing cli_args in worker main\".to_string())\n}","tryCatchPattern":"let cli_args = args.cli_args.ok_or_else(|| anyhow::anyhow!(\"missing cli_args in worker main\"))?;","preventionTips":["Assign cli_args in the dispatcher before every worker_main call","Cover the dispatch wiring with a smoke test that runs the worker subcommand","Avoid invoking worker_main directly from tools or tests without full CliModuleArgs"],"tags":["rust","cli","invariant","arguments"],"backgroundTag":"null-argument","analyzedSha":"e6c3736675048026a057f1c4803d59242482fa7b","analyzedAt":"2026-09-06T15:16:34.240Z","contentChangedAt":"2026-09-06T15:16:34.240Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}