{"record":{"id":"341c919b8c26b2eb","repo":"jdx/mise","slug":"configured-notifications-prepared-services","errorCode":null,"errorMessage":"configured notifications prepared services","messagePattern":"configured notifications prepared services","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/bootstrap.rs","lineNumber":1182,"sourceCode":"                .as_ref()\n                .is_some_and(|(files, directories)| {\n                    files.iter().any(|file| !file.notify.is_empty())\n                        || directories\n                            .iter()\n                            .any(|directory| !directory.notify.is_empty())\n                });\n        let configured_services = if services_enabled || notifications_configured {\n            Some(system::services::prepare_requests_from_config(&config)?)\n        } else {\n            None\n        };\n        if notifications_configured {\n            let (files, directories) = managed_system_files\n                .as_ref()\n                .expect(\"configured notifications came from managed files\");\n            let services = configured_services\n                .as_ref()\n                .expect(\"configured notifications prepared services\");\n            system::services::validate_notifications(files, directories, services)?;\n        }\n        let mut managed_services =\n            services_enabled.then_some(configured_services.unwrap_or_default());\n        let mut managed_firewall = if skip.contains(&BootstrapPart::Firewall) {\n            None\n        } else {\n            system::firewall::prepare_request_from_config(&config)?\n        };\n        let mut managed_compose = if skip.contains(&BootstrapPart::Compose) {\n            None\n        } else {\n            Some(system::compose::prepare_requests_from_config(&config)?)\n        };\n        let dry_run_compose_actions = if self.dry_run\n            && managed_compose\n                .as_ref()\n                .is_some_and(|projects| !projects.is_empty())","sourceCodeStart":1164,"sourceCodeEnd":1200,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/cli/bootstrap.rs#L1164-L1200","documentation":"Internal invariant directly following the previous one: `configured_services` is computed as Some(...) when `services_enabled || notifications_configured` (src/cli/bootstrap.rs:1171-1175). Inside `if notifications_configured`, the unwrap at line 1180-1182 therefore always succeeds because notifications_configured implies the prepare branch ran. The expect is a refactor guard tying notification validation to service preparation.","triggerScenarios":"Only a source change that computes configured_services without including notifications_configured in its condition (or that enters validate_notifications without preparing services) — panics during `mise bootstrap` when notify entries exist. Unreachable via CLI flags in the current code.","commonSituations":"Contributors restructuring the services preflight conditions; broken builds. Real runs with `--skip=services` plus notify config still prepare services precisely because notifications_configured forces the Some branch.","solutions":["If hit as a user: update mise — the build is broken, config is not at fault","Workaround: strip `notify` from bootstrap files/directories config so the validation branch is skipped","As a contributor: keep `services_enabled || notifications_configured` as the prepare condition, or downgrade the expect to a bail! naming the invariant","Report with backtrace at https://github.com/jdx/mise/issues"],"exampleFix":"// before (broken refactor):\nlet configured_services = services_enabled\n    .then(|| system::services::prepare_requests_from_config(&config).ok().flatten()) // None when skipped\n    ...expect(\"configured notifications prepared services\"); // panics\n\n// after: notifications force service preparation\nlet configured_services = if services_enabled || notifications_configured {\n    Some(system::services::prepare_requests_from_config(&config)?)\n} else {\n    None\n};","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare [bootstrap.services] entries alongside any notify configuration so services are always prepared","Validate with mise bootstrap --dry-run after editing notify/services config","Report invariant panics upstream with the config and backtrace"],"tags":["bootstrap","invariant","panic","internal","services","notifications"],"backgroundTag":"internal-invariant-violation","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}