{"record":{"id":"4647e7cb1eb00184","repo":"jdx/mise","slug":"brew-cask-unsupported-target-type-4647e7","errorCode":null,"errorMessage":"brew-cask: unsupported target type '{}'","messagePattern":"brew-cask: unsupported target type '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/state.rs","lineNumber":453,"sourceCode":"        let target = std::fs::read_link(path)?;\n        return Ok(CaskTargetFingerprint {\n            kind: CaskTargetKind::Symlink,\n            digest: hex::encode(Sha256::digest(target.as_os_str().as_encoded_bytes())),\n        });\n    }\n    if metadata.is_file() {\n        return Ok(CaskTargetFingerprint {\n            kind: CaskTargetKind::File,\n            digest: hash::file_hash_sha256(path, None)?,\n        });\n    }\n    if metadata.is_dir() {\n        return Ok(CaskTargetFingerprint {\n            kind: CaskTargetKind::Directory,\n            digest: cask_directory_digest(path)?,\n        });\n    }\n    bail!(\"brew-cask: unsupported target type '{}'\", path.display())\n}\n\n/// Content identity intentionally excludes timestamps, ownership, and modes.\n/// It hashes stable relative paths, entry kinds, file bytes, and link targets\n/// without following symlinks.\npub(super) fn cask_directory_digest(root: &Path) -> Result<String> {\n    let mut entries = WalkDir::new(root)\n        .follow_links(false)\n        .into_iter()\n        .collect::<std::result::Result<Vec<_>, _>>()?;\n    entries.sort_by(|a, b| a.path().cmp(b.path()));\n    let mut digest = Sha256::new();\n    for entry in entries {\n        let path = entry.path();\n        let relative = path.strip_prefix(root)?;\n        if relative.as_os_str().is_empty() {\n            continue;\n        }","sourceCodeStart":435,"sourceCodeEnd":471,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/cask/state.rs#L435-L471","documentation":"cask_target_fingerprint fingerprints an artifact target as either a directory or a file so cask ownership can be verified. The SOURCE shows a dir/file check, and any target whose type is neither (e.g. a dangling symlink, socket, fifo, or device node) cannot be fingerprinted, so mise bails naming the path. This keeps ownership digests well-defined.","triggerScenarios":"cask_target_fingerprint is called (from install_app, validate_adoptable_apps, CaskTargetRecord, cask_target_record_matches, staged_target_matches) on a path whose metadata is not a directory and not a regular file — e.g. a broken symlink at the target location.","commonSituations":"A previous tool left a dangling symlink where an app/binary should live; dev filesystems with sockets or fifos in target locations; corrupted installs.","solutions":["Inspect the reported path (`ls -la <path>`) and remove or replace the non-file/non-directory entry (e.g. delete the dangling symlink)","Run `brew reinstall --cask <token>` to restore a clean target layout","Retry the mise cask operation after the target is a normal file or directory"],"exampleFix":"// shell\n// before: /Applications/MyApp is a broken symlink\n// after:\nrm /Applications/MyApp && mise reinstall <cask-token>","handlingStrategy":"validation","validationCode":"fn fingerprintable(p: &std::path::Path) -> bool {\n    match std::fs::symlink_metadata(p) {\n        Ok(m) => m.is_dir() || m.is_file(),\n        Err(_) => false,\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check symlink_metadata on cask targets before install/adopt; clean dangling symlinks","Reinstall the cask rather than hand-repairing target paths","Avoid leaving sockets/fifos/devices in cask target locations"],"tags":["filesystem","fingerprint","unsupported-type","symlink"],"backgroundTag":"invalid-argument-value","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}