Hmbown/CodeWhale · error · io::Error (InvalidData)

artifact tree exceeds export depth limit

Error message

artifact tree exceeds export depth limit

What it means

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.

Solutions

  1. Flatten or prune the artifact tree: move deeply nested content out of the artifacts directory.
  2. Exclude the offending subdirectory from artifacts (do not write it into the session's artifacts folder in the first place).
  3. Raise MAX_ARTIFACT_DEPTH if your workflow legitimately needs deeper trees (recompile with a larger constant).
  4. Find the deep path with `find <artifacts-dir> -mindepth 20` (or equivalent) and clean it up.

Example fix

// before
// artifacts/ level1/.../level30/file  -> export fails
// after: prune before export
fs::remove_dir_all("<artifacts>/generated/deep-tree")?;
write_session_archive(&session, dir, &out, options)?;
Defensive patterns

Strategy: validation

Validate before calling

fn artifact_depth_ok(dir: &Path, max: usize) -> bool {
    fn walk(d: &Path, depth: usize, max: usize) -> bool {
        depth <= max && std::fs::read_dir(d).map(|rd| rd.filter_map(Result::ok)
            .filter(|e| e.file_type().map(|t| t.is_dir()).unwrap_or(false))
            .all(|e| walk(&e.path(), depth + 1, max))).unwrap_or(false)
    }
    walk(dir, 0, max)
}

Try / catch

match write_session_archive(&session, dir, out, opts) {
    Err(e) if e.to_string().contains("depth limit") => {
        eprintln!("artifact tree too deep; prune nested dirs under {:?}", artifacts_dir);
    }
    other => other?,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/449e774964865849. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/session_export.rs:339

        ARTIFACTS_DIR_NAME,
        0,
        &mut entries,
        &mut files,
    )?;
    files.sort_by(|left, right| left.0.cmp(&right.0));
    Ok(files)
}

fn collect_artifact_files_recursive(
    sessions_dir: &Path,
    dir: &Path,
    prefix: &str,
    depth: usize,
    entries: &mut usize,
    files: &mut Vec<(String, PathBuf)>,
) -> io::Result<()> {
    if depth > MAX_ARTIFACT_DEPTH {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            "artifact tree exceeds export depth limit",
        ));
    }
    for entry in fs::read_dir(dir)? {
        let entry = entry?;
        *entries += 1;
        if *entries > MAX_ARTIFACT_ENTRIES {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "artifact tree exceeds export entry limit",
            ));
        }
        let file_type = entry.file_type()?;
        if file_type.is_symlink() {
            continue;
        }
        let child = entry.file_name();

View on GitHub (pinned to 433685b202)