{"record":{"id":"3b34788292462e8d","repo":"jdx/mise","slug":"brew-cask-structured-copy-source-was-not-fou","errorCode":null,"errorMessage":"brew-cask: structured copy source '{}' was not found","messagePattern":"brew-cask: structured copy source '(.+?)' was not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask.rs","lineNumber":3566,"sourceCode":"            overwrite,\n            source_glob,\n            guards,\n        } => {\n            if !guards\n                .iter()\n                .map(|guard| flight_guard_matches(cask, guard, staged_path, appdir))\n                .collect::<Result<Vec<_>>>()?\n                .into_iter()\n                .all(|matches| matches)\n            {\n                return Ok(());\n            }\n            let sources = flight_symlink_sources(cask, source, *source_glob, staged_path, appdir)?;\n            let [source] = sources.as_slice() else {\n                bail!(\"brew-cask: structured copy source must resolve to exactly one path\");\n            };\n            if !source.exists() {\n                bail!(\n                    \"brew-cask: structured copy source '{}' was not found\",\n                    source.display()\n                );\n            }\n            if source.is_dir() && !recursive {\n                bail!(\"brew-cask: structured directory copy requires recursive=true\");\n            }\n            let target = resolve_flight_path_with_context(cask, target, staged_path, appdir)?;\n            let external = !target.starts_with(staged_path);\n            let target_metadata = target.symlink_metadata().ok();\n            if target_metadata.is_some() {\n                if !overwrite {\n                    bail!(\n                        \"brew-cask: structured copy target '{}' already exists\",\n                        target.display()\n                    );\n                }\n                if external {","sourceCodeStart":3548,"sourceCodeEnd":3584,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/system/packages/brew/cask.rs#L3548-L3584","documentation":"The copy step's source resolved to exactly one path, but that path does not exist on disk (`Path::exists()` follows symlinks, so a dangling symlink also triggers this). The check runs before any target handling, so nothing is created for an absent source.","triggerScenarios":"A non-glob `copy` whose source string names a file missing from the staged payload; a source that is a dangling symlink; template expansion producing a different name than what was staged.","commonSituations":"Upstream renamed the file between cask versions; partial or failed extraction of the staged archive; case-sensitive filesystem versus an archive built on macOS; typo in the source path.","solutions":["Inspect the staged directory and correct the `source` string to the real file name","Use the installer's template variables for version-stamped names so the path stays valid across releases","Re-stage the payload (remove the caskroom staging dir, reinstall) to rule out partial extraction","If the file is optional, guard the step with `if_exists` on the source"],"exampleFix":"# before\ncopy(source: \"bin/mytool-v1.2\", target: \"#{staged}/bin/mytool\")\n# after\ncopy(source: \"bin/mytool-#{version}\", target: \"#{staged}/bin/mytool\")","handlingStrategy":"validation","validationCode":"// Verify the resolved copy source exists before executing the step\nlet source = resolve_flight_path_with_context(cask, &step.source, staged_path, appdir)?;\nif !source.exists() {\n    return Err(eyre!(\"copy source '{}' missing in staged payload; re-stage the cask\", source.display()));\n}","typeGuard":null,"tryCatchPattern":"if err.to_string().contains(\"copy source\") && err.to_string().contains(\"was not found\") {\n    // trigger a re-download/re-stage and retry once before surfacing to the user\n}","preventionTips":["Use version templates instead of hard-coded file names","Verify staged payload contents when the cask definition is written","Treat partial extraction as a first hypothesis: check the caskroom directory size"],"tags":["brew-cask","file-copy","missing-file","install-artifact"],"backgroundTag":"source-file-not-found","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}