{"record":{"id":"56c2fca2c2cbdd35","repo":"Hmbown/CodeWhale","slug":"artifact-tree-exceeds-export-entry-limit","errorCode":null,"errorMessage":"artifact tree exceeds export entry limit","messagePattern":"artifact tree exceeds export entry limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/session_export.rs","lineNumber":348,"sourceCode":"fn 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();\n        let child = child\n            .to_str()\n            .filter(|name| !name.contains(['\\\\', ':']))\n            .ok_or_else(|| {\n                io::Error::new(\n                    io::ErrorKind::InvalidData,\n                    \"artifact name is not portable UTF-8\",\n                )\n            })?;","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/session_export.rs#L330-L366","documentation":"The same recursive walk counts every directory entry it visits and aborts once the total exceeds MAX_ARTIFACT_ENTRIES. This bounds export work and archive size when a session's artifacts directory has become enormous or adversarially filled.","triggerScenarios":"Exporting a session whose artifacts tree contains more than MAX_ARTIFACT_ENTRIES total files/directories, reached from collect_artifact_files via write_session_archive or recursion.","commonSituations":"A long-running session accumulated thousands of artifact files; a test runner or tool dumped logs into artifacts/; a runaway process wrote unbounded output under the session's artifacts dir.","solutions":["Prune old or unneeded files from the session's artifacts/ directory and re-export.","Split the session or export only the needed artifact subsets.","Find and stop the process that flooded the artifacts directory.","If the limit is genuinely too small for your workflow, raise MAX_ARTIFACT_ENTRIES explicitly."],"exampleFix":"// before\n$ ls artifacts/ | wc -l\n50000\n// after\n$ find artifacts/ -mtime +30 -delete   # prune stale artifacts, then re-export","handlingStrategy":"validation","validationCode":"fn entry_count(dir: &Path) -> std::io::Result<u64> {\n    let mut n = 0u64;\n    for e in walkdir_like(dir) { n += 1; }\n    Ok(n)\n}\n// call before export: assert entry_count(artifacts_dir)? <= MAX_ARTIFACT_ENTRIES;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Rotate/prune artifacts per session run instead of accumulating indefinitely.","Monitor artifacts/ size in long-running sessions.","Point noisy tool output at a temp dir, not the session artifacts tree."],"tags":["export","filesystem","limits"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}