{"record":{"id":"77dd064f22f43c33","repo":"windmill-labs/windmill","slug":"internal-error-path-should-not-end-with","errorCode":null,"errorMessage":"Internal error: path should not end with '/'","messagePattern":"Internal error: path should not end with '/'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-worker/src/universal_pkg_installer.rs","lineNumber":531,"sourceCode":"            let layers = graph.layers();\n            (layers, Some((deps_map, nodes_display)))\n        }\n    };\n\n    let mut name_ml = 0;\n    let mut missing_keys: HashSet<String> = HashSet::new();\n    let mut total_missing = 0;\n\n    for layer in layers.iter_mut() {\n        *layer = std::mem::take(layer)\n            .into_iter()\n            .unique_by(|rd| rd.path.clone())\n            .collect();\n\n        let mut missing = vec![];\n        for rd in std::mem::take(layer) {\n            if rd.path.ends_with(\"/\") {\n                anyhow::bail!(\"Internal error: path should not end with '/'\")\n            }\n            if rd.display_name.len() > name_ml {\n                name_ml = rd.display_name.len();\n            }\n            if tokio::fs::metadata(rd.path.clone() + \".valid.windmill\")\n                .await\n                .is_err()\n            {\n                if let Some(key) = rd.path.rsplit('/').next() {\n                    missing_keys.insert(key.to_string());\n                }\n                missing.push(rd);\n            }\n        }\n        total_missing += missing.len();\n        *layer = missing;\n    }\n","sourceCodeStart":513,"sourceCodeEnd":549,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-worker/src/universal_pkg_installer.rs#L513-L549","documentation":"Before checking which dependencies are missing, `filter_to_missing` dedupes RequiredDependency entries and asserts an internal invariant: each dependency's install path must not end with '/'. A trailing slash would corrupt the `<path>.valid.windmill` marker lookup, so it fails fast as an internal construction bug rather than a user-facing problem.","triggerScenarios":"Any dependency install path reaching par_install_language_dependencies_all_at_once or _seq whose RequiredDependency.path was built with a trailing slash — a path-building bug in a language executor's dependency construction (e.g. `format!(\"{dir}/\")`) or a trailing-slash URL leaking into the composed path.","commonSituations":"After customizing or extending a language executor's path-building code; a registry/mirror URL with a trailing slash used in path composition; hand-edited or plugin-generated dependency entries.","solutions":["Fix the code that builds RequiredDependency.path so it never appends a trailing '/' (e.g. `trim_end_matches('/')` when composing from URLs or directory joins)","Audit custom/patched executor or extension code that constructs dependency paths","If caused by a configured repository URL ending in '/', remove the trailing slash from the configuration"],"exampleFix":"// before\nlet path = format!(\"{repo_url}/{group}/{artifact}/{version}/\");\n// after\nlet path = format!(\"{}/{}/{artifact}/{version}\", repo_url.trim_end_matches('/'));","handlingStrategy":"validation","validationCode":"// guard before constructing/installing in custom code\nassert!(!dep.path.ends_with('/'), \"dependency path must not end with '/': {}\", dep.path);","typeGuard":"fn valid_dep_path(rd: &RequiredDependency) -> bool {\n    !rd.path.ends_with('/')\n}","tryCatchPattern":null,"preventionTips":["Always trim trailing slashes when composing paths from URLs or user config","Add unit tests asserting constructed dependency paths have no trailing slash","Never join path components with separators on both sides of a concatenation"],"tags":["internal-invariant","paths","dependencies","bug"],"backgroundTag":"invalid-path-trailing-slash","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}