{"record":{"id":"f15f9cf69909b645","repo":"Hmbown/CodeWhale","slug":"pinned-source-is-missing-non-regular-or-exceeds-the-context","errorCode":null,"errorMessage":"Pinned source is missing, non-regular or exceeds the context limit","messagePattern":"Pinned source is missing, non-regular or exceeds the context limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/review_pr.rs","lineNumber":432,"sourceCode":"    let listing = run_command(\n        workspace,\n        Program::Git,\n        &[\n            \"--literal-pathspecs\".into(),\n            \"ls-tree\".into(),\n            \"--full-tree\".into(),\n            \"-zl\".into(),\n            head_sha.into(),\n            \"--\".into(),\n            path.into(),\n        ],\n    )?;\n    let (header, returned_path) = listing\n        .trim_end_matches('\\0')\n        .split_once('\\t')\n        .context(\"No pinned source blob\")?;\n    let fields = header.split_whitespace().collect::<Vec<_>>();\n    anyhow::ensure!(\n        returned_path == path\n            && fields.len() == 4\n            && matches!(fields[0], \"100644\" | \"100755\")\n            && fields[1] == \"blob\"\n            && commit_id(fields[2])\n            && fields[3]\n                .parse::<usize>()\n                .is_ok_and(|size| size <= MAX_CONTEXT_FILE_BYTES),\n        \"Pinned source is missing, non-regular or exceeds the context limit\"\n    );\n    let source = run_command(\n        workspace,\n        Program::Git,\n        &[\"cat-file\".into(), \"blob\".into(), fields[2].into()],\n    )?;\n    anyhow::ensure!(\n        source.len() <= MAX_CONTEXT_FILE_BYTES && !source.contains('\\0'),\n        \"Pinned source is not bounded text\"","sourceCodeStart":414,"sourceCodeEnd":450,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tools/review_pr.rs#L414-L450","documentation":"`context_blob` resolves a pinned file's source blob via `git ls-tree` and validates the returned metadata: the path must match the requested one, the mode must be a regular executable-or-not file (100644/100755), the object type must be `blob`, and the object id must be a valid commit/blob id. Any deviation — missing path, submodule (commit object), symlink, or malformed listing — means the pinned source cannot be safely read.","triggerScenarios":"Calling `source_context`/`context_blob` for a path that is a symlink (120000), a submodule (160000 commit), absent from the pinned tree, or whose `git ls-tree -z` output is malformed (wrong field count, path mismatch, invalid object id).","commonSituations":"Reviewing a PR that adds symlinks or submodules; a path containing tabs/odd characters mishandled by parsing; requesting a file that only exists in the working checkout, not the pinned commit; renamed/moved files queried by an old path.","solutions":["Skip non-regular pinned entries (symlinks/submodules) or resolve them explicitly before review","Verify the requested path exists in the pinned commit's tree (`git ls-tree <commit> -- <path>`)","Re-pin the review to a commit that actually contains the file as a regular blob"],"exampleFix":"// before\nlet src = context_blob(ws, pinned_commit, \"docs/link.md\")?;\n// after\nlet mode = tree_entry_mode(ws, pinned_commit, \"docs/link.md\")?;\nif !matches!(mode.as_str(), \"100644\" | \"100755\") {\n    return Ok(None); // symlink or submodule: no bounded text source\n}\nlet src = context_blob(ws, pinned_commit, \"docs/link.md\")?;","handlingStrategy":"validation","validationCode":"let out = git([\"ls-tree\", commit, \"--\", path])?; let regular = out.starts_with(\"100644 \") || out.starts_with(\"100755 \"); if !regular { skip_or_handle(path); }","typeGuard":null,"tryCatchPattern":"match source_context(ws, commit, path) { Ok(src) => Some(src), Err(e) if e.to_string().contains(\"Pinned source\") => { warn!(\"skipping non-regular pinned entry {path}\"); None }, Err(e) => return Err(e) }","preventionTips":["Avoid symlinks and submodules in reviewed trees, or special-case them","Resolve paths against the pinned commit, not the working checkout","Sanitize/validate paths with unusual characters before ls-tree parsing"],"tags":["git","review","pinning","validation"],"backgroundTag":"unexpected-response-shape","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"}