{"record":{"id":"807cf5f3d7839179","repo":"cross-rs/cross","slug":"should-contain-one-item","errorCode":null,"errorMessage":"should contain one item","messagePattern":"should contain one item","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"info","filePath":"src/config.rs","lineNumber":151,"sourceCode":"    fn image(&self, target: &Target) -> Result<Option<PossibleImage>> {\n        let get_target = |env: &Environment, var: &str| env.get_target_var(target, var);\n        get_possible_image(self, \"IMAGE\", \"IMAGE_TOOLCHAIN\", get_target, get_target)\n    }\n\n    fn dockerfile(&self, target: &Target) -> ConfVal<String> {\n        self.get_values_for(\"DOCKERFILE\", target, ToOwned::to_owned)\n    }\n\n    fn dockerfile_context(&self, target: &Target) -> ConfVal<String> {\n        self.get_values_for(\"DOCKERFILE_CONTEXT\", target, ToOwned::to_owned)\n    }\n\n    fn pre_build(&self, target: &Target) -> ConfVal<PreBuild> {\n        self.get_values_for(\"PRE_BUILD\", target, |v| {\n            let v: Vec<_> = v.split('\\n').map(String::from).collect();\n            if v.len() == 1 {\n                PreBuild::Single {\n                    line: v.into_iter().next().expect(\"should contain one item\"),\n                    env: true,\n                }\n            } else {\n                PreBuild::Lines(v)\n            }\n        })\n    }\n\n    fn runner(&self, target: &Target) -> Option<String> {\n        self.get_target_var(target, \"RUNNER\")\n    }\n\n    fn passthrough(&self, target: &Target) -> ConfVal<Vec<String>> {\n        self.get_values_for(\"ENV_PASSTHROUGH\", target, split_to_cloned_by_ws)\n    }\n\n    fn volumes(&self, target: &Target) -> ConfVal<Vec<String>> {\n        self.get_values_for(\"ENV_VOLUMES\", target, split_to_cloned_by_ws)","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/cross-rs/cross/blob/8c1a8aa4b661711f4b7b6ac07c2e8929ce2f7d27/src/config.rs#L133-L169","documentation":"This `expect` fires inside PreBuild::Single construction in `pre_build` (src/config.rs:151). After `split('\\n')` and a `v.len() == 1` check, the code re-collects into a Vec and calls `next().expect(\"should contain one item\")`. The expect documents the invariant that a single-element iterator always yields one item; it can only fail if that invariant is broken, which is logically unreachable with a correctly-checked len==1.","triggerScenarios":"Only reachable if the `v.len() == 1` guard is bypassed or the Vec is emptied between the check and the `next()` call. In practice this never fires for users; it is a defensive assertion. A PRE_BUILD config value with no newline (single line) takes this branch.","commonSituations":"Developers essentially never hit this at runtime; it surfaces as a panic in code review or fuzzing if the guard were ever removed. Confusion usually comes from reading the expect message and thinking a config file was malformed.","solutions":["Treat this as an internal invariant, not a config error; if it ever fires, report it as a bug in cross","If refactoring, avoid the re-collect: use `v.into_iter().next().unwrap()` immediately after the len check, or match on the slice `if let [line] = &v[..]`","For config problems, check the PRE_BUILD value in Cross.toml instead — single-line vs multi-line is decided by the len==1 branch, not this expect"],"exampleFix":"// before\nif v.len() == 1 {\n    PreBuild::Single { line: v.into_iter().next().expect(\"should contain one item\"), env: true }\n}\n// after\nif let [line] = v.as_slice() {\n    PreBuild::Single { line: line.clone(), env: true }\n}","handlingStrategy":"validation","validationCode":"let lines: Vec<&str> = pre_build_value.split('\\n').collect();\nif lines.len() != 1 { /* it will take the PreBuild::Lines branch; no panic path */ }","typeGuard":"fn is_single_line(v: &str) -> bool { !v.contains('\\n') }","tryCatchPattern":null,"preventionTips":["Don't try to 'fix' config values for this error — it is an unreachable internal assertion","When contributing to cross, keep the length check adjacent to the expect so the invariant stays provable"],"tags":["rust","unwrap-expect","config-parsing"],"backgroundTag":"internal-invariant-violation","analyzedSha":"8c1a8aa4b661711f4b7b6ac07c2e8929ce2f7d27","analyzedAt":"2026-09-13T15:10:43.988Z","contentChangedAt":"2026-09-13T15:10:43.988Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}