{"record":{"id":"922aaeed3549d615","repo":"jdx/mise","slug":"tap-repository-tree-was-truncated","errorCode":null,"errorMessage":"tap repository tree was truncated","messagePattern":"tap repository tree was truncated","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/tap.rs","lineNumber":261,"sourceCode":"    let mut parts = rest.split('/');\n    match (parts.next(), parts.next(), parts.next()) {\n        (Some(repo_owner), Some(repo), None) if !repo_owner.is_empty() && !repo.is_empty() => {\n            Ok((repo_owner, repo.to_string()))\n        }\n        _ => bail!(\"invalid GitHub tap URL '{url}'\"),\n    }\n}\n\nasync fn fetch_formula_source(tap_source: &TapSource, name: &str) -> Result<(String, String)> {\n    let root_tree: GithubTree = HTTP_FETCH\n        .json_cached(format!(\n            \"{}/git/trees/{}\",\n            tap_source.api_base, tap_source.commit\n        ))\n        .await\n        .wrap_err(\"failed to inspect tap formula directories\")?;\n    if root_tree.truncated {\n        bail!(\"tap repository tree was truncated\");\n    }\n\n    let (directory, formula_tree) =\n        if let Some((directory, sha)) = active_formula_directory(&root_tree) {\n            let tree: GithubTree = HTTP_FETCH\n                .json_cached(format!(\n                    \"{}/git/trees/{sha}?recursive=1\",\n                    tap_source.api_base\n                ))\n                .await\n                .wrap_err_with(|| format!(\"failed to inspect tap {directory} directory\"))?;\n            if tree.truncated {\n                bail!(\"tap {directory} directory tree was truncated\");\n            }\n            (directory, tree)\n        } else {\n            (\"\", root_tree)\n        };","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/tap.rs#L243-L279","documentation":"When inspecting a Homebrew tap via the GitHub API (GET /git/trees/{commit}), the response can carry truncated=true, meaning GitHub omitted entries because the tree is too large. The library refuses to continue because formula discovery would silently miss directories/files, so it bails with this error rather than return incomplete results.","triggerScenarios":"fetch_formula_source calls the GitHub trees API for the tap's commit and the returned root tree has truncated=true — i.e. the tap repository tree exceeds GitHub's tree API limits (very large repos, taps with thousands of entries or huge non-formula directories).","commonSituations":"Querying very large or monorepo-style taps (e.g. homebrew/cask or an enormous personal tap) whose root tree exceeds GitHub's size cap; network-level API usage without any narrowing ref; GitHub truncating trees for repos with tens of thousands of objects.","solutions":["Retry the operation — truncation can occasionally vary, though for genuinely oversized trees it will recur.","Use a full git clone of the tap instead of the GitHub trees API, then read the formula locally.","Narrow the query to a specific subdirectory or path so the returned tree stays under GitHub's limits.","Pin to a specific commit whose tree is smaller, or split the tap into smaller taps."],"exampleFix":"// before: relying on trees API for a huge tap\nlet tree = github_tree(api_base, commit).await?;\n// after: fall back to a local clone when the API tree is truncated\nlet tree = match github_tree(api_base, commit).await {\n    Ok(t) if !t.truncated => t,\n    _ => clone_and_read_tap_locally(tap_url, commit).await?,\n};","handlingStrategy":"retry","validationCode":"// No client-side pre-check possible; GitHub sets truncated itself.\n// Detect it after the call and fall back:\nlet tree: GithubTree = resp.json().await?;\nif tree.truncated { /* fall back to git clone */ }","typeGuard":"fn is_complete_tree(t: &GithubTree) -> bool { !t.truncated }","tryCatchPattern":"match fetch_formula_source(tap, name).await {\n    Err(e) if e.to_string().contains(\"truncated\") => clone_tap_and_read_locally(tap, name).await,\n    other => other,\n}","preventionTips":["Prefer a local git clone for very large taps instead of the trees API","Keep taps small; avoid monorepo-scale tap repositories","Cache successful tree responses and only re-query on commit change"],"tags":["network","github-api","homebrew","tap"],"backgroundTag":"http-error-response","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"}