{"record":{"id":"aa1ad9a6edb87c15","repo":"Hmbown/CodeWhale","slug":"bundle-exceeds-the-max-bundle-files-file-limit","errorCode":null,"errorMessage":"bundle exceeds the {MAX_BUNDLE_FILES} file limit","messagePattern":"bundle exceeds the (.+?) file limit","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/plugins/install/stage.rs","lineNumber":165,"sourceCode":"        let entry = entry?;\n        let path = entry.path();\n        let metadata = fs::symlink_metadata(&path)?;\n        if metadata.file_type().is_symlink() {\n            return Err(PluginInstallError::SymlinkRejected.into());\n        }\n        let name = entry.file_name();\n        if name == std::ffi::OsStr::new(INSTALLED_FROM_MARKER) {\n            continue;\n        }\n        let target = dest.join(&name);\n        if metadata.is_dir() {\n            fs::create_dir(&target)\n                .with_context(|| format!(\"failed to create {}\", target.display()))?;\n            copy_bundle_regular_files(&path, &target, max_size, budget)?;\n        } else if metadata.is_file() {\n            budget.files = budget.files.saturating_add(1);\n            if budget.files > MAX_BUNDLE_FILES {\n                bail!(\"bundle exceeds the {MAX_BUNDLE_FILES} file limit\");\n            }\n            budget.bytes = budget.bytes.saturating_add(metadata.len());\n            if budget.bytes > max_size {\n                return Err(PluginInstallError::OversizedBundle { limit: max_size }.into());\n            }\n            fs::copy(&path, &target).with_context(|| {\n                format!(\"failed to copy {} to {}\", path.display(), target.display())\n            })?;\n        }\n    }\n    Ok(())\n}\n","sourceCodeStart":147,"sourceCodeEnd":178,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/plugins/install/stage.rs#L147-L178","documentation":"Bundles are capped at `MAX_BUNDLE_FILES` entries. While recursively copying regular files, `copy_bundle_regular_files` increments a shared budget; when the file count exceeds the cap it bails immediately (byte-size overflow raises `OversizedBundle` separately).","triggerScenarios":"Installing a local bundle (via `stage_local_copy`) that contains more files than `MAX_BUNDLE_FILES`, including files nested in subdirectories — the recursion calls itself, so the count accumulates across the whole tree.","commonSituations":"Pointing `/plugin install` at a whole repo or `node_modules`-style tree instead of a trimmed bundle directory; a build dir with generated artifacts included; vendored dependencies shipped in the bundle.","solutions":["Reduce the bundle contents: install a curated directory containing only the plugin's needed files","Add excludes when packaging (e.g. skip `node_modules`, `target`, `.git`) so the file count drops under the limit","Split very large plugins into multiple smaller bundles"],"exampleFix":"// before: installing the whole repo including node_modules\n/plugin install ~/projects/myplugin\n// after: package only dist\ncd ~/projects/myplugin && tar -czf /tmp/myplugin.tar.gz -C dist .\n/plugin install /tmp/myplugin.tar.gz","handlingStrategy":"validation","validationCode":"let file_count = walk(source_dir)\n    .filter(|p| p.is_file())\n    .count();\nif file_count > MAX_BUNDLE_FILES {\n    eprintln!(\"bundle has {file_count} files; trim to under the limit\");\n    return;\n}","typeGuard":null,"tryCatchPattern":"match install(path) {\n    Err(e) if e.to_string().contains(\"file limit\") => {\n        eprintln!(\"too many files; exclude build/vendor dirs and retry\");\n    }\n    Err(e) if e.to_string().contains(\"OversizedBundle\") => {\n        eprintln!(\"bundle too large in bytes; trim contents\");\n    }\n    other => other?,\n}","preventionTips":["Install a curated bundle directory, not a whole repo","Exclude node_modules, target, .git and other generated trees","Count files in CI before publishing plugin bundles"],"tags":["plugins","install","limit"],"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"}