{"record":{"id":"a7b6d6786148b625","repo":"sinelaw/fresh","slug":"plugin-depends-on-which-is-not-installed-or-not-enabled","errorCode":null,"errorMessage":"Plugin '{}' depends on '{}', which is not installed or not enabled","messagePattern":"Plugin '(.+?)' depends on '(.+?)', which is not installed or not enabled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-parser-js/src/lib.rs","lineNumber":223,"sourceCode":"    let mut in_degree: HashMap<&str, usize> = HashMap::new();\n    let mut dependents: HashMap<&str, Vec<&str>> = HashMap::new();\n\n    for name in plugin_names {\n        in_degree.entry(name.as_str()).or_insert(0);\n    }\n\n    for name in plugin_names {\n        if let Some(deps) = dependencies.get(name) {\n            for dep in deps {\n                // Only count dependencies on plugins that exist in our set\n                if in_degree.contains_key(dep.as_str()) {\n                    *in_degree.entry(name.as_str()).or_insert(0) += 1;\n                    dependents\n                        .entry(dep.as_str())\n                        .or_default()\n                        .push(name.as_str());\n                } else {\n                    return Err(anyhow!(\n                        \"Plugin '{}' depends on '{}', which is not installed or not enabled\",\n                        name,\n                        dep\n                    ));\n                }\n            }\n        }\n    }\n\n    // Kahn's algorithm\n    let mut queue: Vec<&str> = in_degree\n        .iter()\n        .filter(|(_, &deg)| deg == 0)\n        .map(|(&name, _)| name)\n        .collect();\n    // Sort the initial queue alphabetically for determinism\n    queue.sort();\n","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-parser-js/src/lib.rs#L205-L241","documentation":"During dependency resolution, `topological_sort_plugins` found a plugin whose declared dependency is absent from the plugin map (not installed, or installed but disabled). It fails fast with both names so the misconfiguration is obvious rather than loading a partial graph.","triggerScenarios":"Calling `topological_sort_plugins` with a plugin set where plugin A lists plugin B in its dependencies but B is missing, disabled, or renamed.","commonSituations":"Config lists a plugin that was removed/renamed; a plugin enabled in config whose dependency is not in the plugins directory; typo in a dependency name.","solutions":["Install or enable the named dependency plugin listed in the message.","Fix the dependency name typo in the depending plugin's metadata/config.","Remove the dependency entry if it is no longer needed."],"exampleFix":"// before (config)\nplugins = [{ name = \"a\", deps = [\"b\"] }] // b missing\n// after\nplugins = [\n  { name = \"b\" },\n  { name = \"a\", deps = [\"b\"] },\n]","handlingStrategy":"validation","validationCode":"// Pre-check: every declared dep exists in the enabled plugin map\nfor p in &plugins {\n    for dep in &p.deps {\n        assert!(plugins.iter().any(|q| &q.name == dep), \"missing dep {} for {}\", dep, p.name);\n    }\n}","typeGuard":null,"tryCatchPattern":"match topological_sort_plugins(&plugins) {\n    Err(e) if e.to_string().contains(\"not installed or not enabled\") => fix_config_and_retry(),\n    other => other?,\n}","preventionTips":["Keep the enabled-plugin list generated from the same source as dependency metadata.","Validate plugin config at startup with a dependency existence check.","Avoid renaming plugins without bumping dependents' metadata."],"tags":["plugins","dependencies","configuration"],"backgroundTag":"missing-dependency","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}