{"record":{"id":"75a010959d3fea09","repo":"jdx/mise","slug":"executor-must-be-initialized-before-displaying-cac","errorCode":null,"errorMessage":"executor must be initialized before displaying cache stats","messagePattern":"executor must be initialized before displaying cache stats","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/run.rs","lineNumber":1409,"sourceCode":"            } else {\n                bail!(\n                    \"`{dp}` is not executable. {}\",\n                    file::make_executable_hint(path)\n                )\n            }\n        }\n        Ok(())\n    }\n\n    fn timings(&self) -> bool {\n        !self.quiet(None) && !self.no_timings\n    }\n\n    fn display_task_cache_stats(&self) {\n        let stats = *self\n            .executor\n            .as_ref()\n            .expect(\"executor must be initialized before displaying cache stats\")\n            .cache_stats\n            .lock()\n            .unwrap();\n        let lookups = stats.hits.saturating_add(stats.misses);\n        if lookups == 0 {\n            safe_eprintln!(\"Task cache: no lookups\");\n            return;\n        }\n        let hit_rate = stats.hits.saturating_mul(100) / lookups;\n        safe_eprintln!(\n            \"Task cache: {}/{} hits ({}%), {} restored, {} saved\",\n            stats.hits,\n            lookups,\n            hit_rate,\n            ByteSize::b(stats.restored_bytes).display().iec(),\n            crate::ui::time::format_duration(stats.time_saved),\n        );\n    }","sourceCodeStart":1391,"sourceCodeEnd":1427,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/cli/run.rs#L1391-L1427","documentation":"After a `mise run` that used the task action cache, mise prints hit/miss statistics by locking `executor.cache_stats`; the executor is obtained via `self.executor.as_ref().expect(\"executor must be initialized before displaying cache stats\")` (src/cli/run.rs:1404-1412). display_task_cache_stats is called from the run flow after setup_executor has run, so the expect guards against the call site drifting to paths where no executor exists (e.g. non-run commands).","triggerScenarios":"A refactor that calls display_task_cache_stats from a context where the run pipeline was not entered (setup_executor skipped or failed silently), or that caches stats display across invocations. The normal path — `mise run <task>` with cache lookups — always has Some(executor) by the time stats are printed.","commonSituations":"Contributors sharing the stats printer with other commands or moving it earlier in the flow; broken builds. Users see 'Task cache: N/M hits (...)' normally; this panic means the printer ran executor-less.","solutions":["If hit: update mise — display of cache stats ran without an initialized run pipeline","As a contributor: gate the call with `if let Some(executor) = &self.executor { ... }` or move it strictly after setup_executor","Consider storing cache stats outside the executor if they must outlive it","Report at https://github.com/jdx/mise/issues"],"exampleFix":"// before: unconditional call on a maybe-absent executor\nfn display_task_cache_stats(&self) {\n    let stats = *self.executor.as_ref().expect(\"...\").cache_stats.lock().unwrap();\n}\n\n// after: tolerate absence\nfn display_task_cache_stats(&self) {\n    let Some(executor) = &self.executor else { return; };\n    let stats = *executor.cache_stats.lock().unwrap();\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Report the panic with the mise run invocation — stats display ran executor-less","Contributors: guard the stats printer with the executor's presence or move it after setup","Pin released versions in automation"],"tags":["run","task-cache","invariant","panic","internal","stats"],"backgroundTag":"internal-invariant-violation","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}