{"record":{"id":"91f709a54f2004c7","repo":"louis-e/arnis","slug":"provider-chain-is-never-empty","errorCode":null,"errorMessage":"provider chain is never empty","messagePattern":"provider chain is never empty","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/elevation/mod.rs","lineNumber":325,"sourceCode":"                    name,\n                    e,\n                    chain[i + 1].name()\n                );\n                #[cfg(feature = \"gui\")]\n                crate::telemetry::send_log(\n                    crate::telemetry::LogLevel::Warning,\n                    &format!(\n                        \"Elevation provider '{}' failed, falling back to '{}'.\",\n                        name,\n                        chain[i + 1].name()\n                    ),\n                );\n                emit_gui_progress_update(10.0, \"Downloading data...\");\n            }\n            Err(e) => return Err(e),\n        }\n    }\n    unreachable!(\"provider chain is never empty\")\n}\n\n/// Compute the fraction of NaN/non-finite values in a height grid (0.0 to 1.0).\nfn compute_nan_ratio(heights: &[Vec<f64>]) -> f64 {\n    let mut total = 0usize;\n    let mut nan_count = 0usize;\n    for row in heights {\n        for &h in row {\n            total += 1;\n            if !h.is_finite() {\n                nan_count += 1;\n            }\n        }\n    }\n    if total == 0 {\n        return 1.0;\n    }\n    nan_count as f64 / total as f64","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/louis-e/arnis/blob/34048924d9365795fb0d832e76140a3fbdc413d9/src/elevation/mod.rs#L307-L343","documentation":"`fetch_raw_with_fallback` iterates a chain of elevation data providers and, if the loop ends without returning, hits `unreachable!(\"provider chain is never empty\")`. The invariant assumes the provider chain is constructed with at least one provider, so the only way to reach this line is an empty chain.","triggerScenarios":"Building the provider list with configuration that selects zero providers (e.g. all elevation sources disabled, an empty/invalid config, or a feature-gated build where every provider is compiled out) and then calling `fetch_elevation_data`.","commonSituations":"Config file with all elevation providers turned off; CLI flags excluding every source; a build without the default provider features enabled.","solutions":["Ensure at least one elevation provider is configured/enabled before calling `fetch_elevation_data`","Validate the provider chain is non-empty early and return a proper `Err(String)` like \"no elevation providers configured\" instead of relying on unreachable!","Enable the default provider feature or add a fallback provider to the chain construction"],"exampleFix":"// before\nunreachable!(\"provider chain is never empty\")\n// after\nErr(anyhow!(\"no elevation providers configured\"))","handlingStrategy":"validation","validationCode":"if providers.is_empty() { return Err(anyhow!(\"no elevation providers configured; enable at least one source\")); }","typeGuard":"fn has_provider(chain: &[Box<dyn ElevationProvider>]) -> bool { !chain.is_empty() }","tryCatchPattern":null,"preventionTips":["Validate provider configuration at startup, before fetching","Never allow config that disables every elevation source without a fallback","Enable default provider features in builds"],"tags":["panic","unreachable","elevation","configuration"],"backgroundTag":"empty-provider-chain","analyzedSha":"34048924d9365795fb0d832e76140a3fbdc413d9","analyzedAt":"2026-09-03T14:05:17.283Z","contentChangedAt":"2026-09-03T14:05:17.283Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}