{"record":{"id":"449e774964865849","repo":"Hmbown/CodeWhale","slug":"artifact-tree-exceeds-export-depth-limit","errorCode":null,"errorMessage":"artifact tree exceeds export depth limit","messagePattern":"artifact tree exceeds export depth limit","errorType":"validation","errorClass":"io::Error (InvalidData)","httpStatus":null,"severity":"error","filePath":"crates/tui/src/session_export.rs","lineNumber":339,"sourceCode":"        ARTIFACTS_DIR_NAME,\n        0,\n        &mut entries,\n        &mut files,\n    )?;\n    files.sort_by(|left, right| left.0.cmp(&right.0));\n    Ok(files)\n}\n\nfn collect_artifact_files_recursive(\n    sessions_dir: &Path,\n    dir: &Path,\n    prefix: &str,\n    depth: usize,\n    entries: &mut usize,\n    files: &mut Vec<(String, PathBuf)>,\n) -> io::Result<()> {\n    if depth > MAX_ARTIFACT_DEPTH {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            \"artifact tree exceeds export depth limit\",\n        ));\n    }\n    for entry in fs::read_dir(dir)? {\n        let entry = entry?;\n        *entries += 1;\n        if *entries > MAX_ARTIFACT_ENTRIES {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                \"artifact tree exceeds export entry limit\",\n            ));\n        }\n        let file_type = entry.file_type()?;\n        if file_type.is_symlink() {\n            continue;\n        }\n        let child = entry.file_name();","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/session_export.rs#L321-L357","documentation":"collect_artifact_files_recursive walks the session's artifact tree and enforces MAX_ARTIFACT_DEPTH: if the recursion depth exceeds that constant the walk aborts with InvalidData. This bounds the walk so a pathological or hostile artifact tree (or a symlink-following cycle, though symlinks are skipped) cannot cause unbounded recursion or memory use during export.","triggerScenarios":"Exporting a session whose artifacts directory contains nesting deeper than MAX_ARTIFACT_DEPTH — e.g. deeply nested generated output, or an extracted archive accidentally placed inside the artifacts folder.","commonSituations":"A build tool or test runner wrote deep output trees (node_modules, target/, temp extraction dirs) into the session artifacts folder; programmatically generated fixtures with very deep nesting.","solutions":["Flatten or prune the artifact tree: move deeply nested content out of the artifacts directory.","Exclude the offending subdirectory from artifacts (do not write it into the session's artifacts folder in the first place).","Raise MAX_ARTIFACT_DEPTH if your workflow legitimately needs deeper trees (recompile with a larger constant).","Find the deep path with `find <artifacts-dir> -mindepth 20` (or equivalent) and clean it up."],"exampleFix":"// before\n// artifacts/ level1/.../level30/file  -> export fails\n// after: prune before export\nfs::remove_dir_all(\"<artifacts>/generated/deep-tree\")?;\nwrite_session_archive(&session, dir, &out, options)?;","handlingStrategy":"validation","validationCode":"fn artifact_depth_ok(dir: &Path, max: usize) -> bool {\n    fn walk(d: &Path, depth: usize, max: usize) -> bool {\n        depth <= max && std::fs::read_dir(d).map(|rd| rd.filter_map(Result::ok)\n            .filter(|e| e.file_type().map(|t| t.is_dir()).unwrap_or(false))\n            .all(|e| walk(&e.path(), depth + 1, max))).unwrap_or(false)\n    }\n    walk(dir, 0, max)\n}","typeGuard":null,"tryCatchPattern":"match write_session_archive(&session, dir, out, opts) {\n    Err(e) if e.to_string().contains(\"depth limit\") => {\n        eprintln!(\"artifact tree too deep; prune nested dirs under {:?}\", artifacts_dir);\n    }\n    other => other?,\n}","preventionTips":["Don't dump extracted archives or build outputs into the artifacts folder","Prune generated trees before export","Check depth with find -mindepth before exporting large sessions"],"tags":["filesystem","limits","session-export","recursion"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}