{"record":{"id":"508ed8f41defbe5f","repo":"jdx/mise","slug":"task-executor-initialized","errorCode":null,"errorMessage":"task executor initialized","messagePattern":"task executor initialized","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/run.rs","lineNumber":883,"sourceCode":"        self.setup_output_and_validate(&tasks)?;\n        self.output = Some(self.output(None));\n\n        // Step 3: Install tools needed by tasks\n        if !self.skip_tools {\n            self.install_task_tools(&mut config, &tasks, &previewed_tools)\n                .await?;\n        }\n\n        // Step 4: Bracket action caching with this top-level task run. The\n        // session owns the local agent and is flushed before results report.\n        self.setup_cache_session(&tasks).await?;\n\n        // Step 5: Create TaskExecutor after tool installation\n        self.setup_executor()?;\n\n        // Validate every scheduled invocation before starting the scheduler so\n        // an invalid parent or dependency cannot run any task commands first.\n        let executor = self.executor.as_ref().expect(\"task executor initialized\");\n        for task in tasks.all() {\n            if let Err(err) = executor\n                .preflight_task_usage(&config, task)\n                .await\n                .wrap_err_with(|| format!(\"failed to validate task {}\", task.name))\n            {\n                if let Some(session) = &self.cache_session\n                    && let Err(finish_err) = session.finish().await\n                {\n                    warn!(\"failed to finish action cache session: {finish_err:#}\");\n                }\n                return Err(err);\n            }\n        }\n\n        // Disable exit-on-ctrl-c so tasks can handle SIGINT gracefully\n        ctrlc::exit_on_ctrl_c(false);\n","sourceCodeStart":865,"sourceCodeEnd":901,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/cli/run.rs#L865-L901","documentation":"In `mise run` setup, Step 5 calls `self.setup_executor()?` and immediately afterwards borrows `self.executor.as_ref().expect(\"task executor initialized\")` to preflight every scheduled invocation (validating tasks/deps before anything executes, src/cli/run.rs:877-894). setup_executor returns Err on failure, so reaching the loop with executor == None means the setup step skipped initialization without erroring — an internal wiring invariant.","triggerScenarios":"A refactor that makes setup_executor conditionally leave executor as None (returning Ok), or a new code path that reaches the preflight loop without calling setup_executor. The normal `mise run` flow (including --dry-run and cache sessions) always initializes the executor or aborts with the setup error.","commonSituations":"Contributors adding new run modes that bypass executor setup; broken builds. Users cannot trigger it via task configs — bad task configs surface in the preflight itself as 'failed to validate task <name>' errors, not this panic.","solutions":["If hit as a user: update/pin a released mise build — the run pipeline in that build is broken","As a contributor: make setup_executor unconditionally store Some(executor) or return Err; never return Ok with the field unset","Add a debug_assert!(self.executor.is_some()) at the end of setup_executor so regressions fail fast in debug builds","Report at https://github.com/jdx/mise/issues with the panic backtrace and `mise run` invocation"],"exampleFix":"// before: setup can silently skip\nfn setup_executor(&mut self) -> Result<()> {\n    if self.tasks.is_empty() { return Ok(()); } // executor stays None -> later panic\n    self.executor = Some(TaskExecutor::new(...));\n    Ok(())\n}\n\n// after: always initialize or fail\nfn setup_executor(&mut self) -> Result<()> {\n    self.executor = Some(TaskExecutor::new(...)?);\n    Ok(())\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pin released mise builds in CI; this guard only breaks via internal refactor","Contributors: have setup_executor either store Some(executor) or return Err — never Ok with None","Report panic backtraces with the mise run invocation upstream"],"tags":["run","task-executor","invariant","panic","internal"],"backgroundTag":"internal-invariant-violation","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}