fix(ui): cap expanded context source reads#367
Conversation
Greptile SummaryThis PR prevents large files from freezing the UI during inline context expansion by capping source reads at 1 MB across all three source kinds (filesystem,
Confidence Score: 4/5Safe to merge — the cap correctly prevents memory exhaustion and the UI path is well-covered by new tests; two minor logic gaps are worth addressing in a follow-up. The streaming kill logic, the fs size-check, and the new UI label all work correctly and are tested end-to-end. Two issues are worth noting: the toggleGap skip-fetch guard doesn't include the too-large terminal state, so every subsequent gap interaction on an over-limit file spawns and immediately kills a fresh git show subprocess; and a SourceTextTooLargeError thrown from the 64 KB stderr reader would be misreported as 'source too large' even when the actual source content was within budget. Neither issue causes data loss or a crash, but both are real misbehaviors on the changed paths. src/core/fileSource.ts and src/ui/hooks/useReviewController.ts warrant a second look for the two logic gaps described in the inline comments. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[toggleGap called] --> B{currentStatus?}
B -- loaded / loading --> C[Skip fetch — return early]
B -- error / undefined --> D[Spawn source load request]
D --> E[file.sourceFetcher.getFullText]
E --> F{Result?}
F -- text !== null --> G[setSettledStatus loaded]
F -- text === null --> H[setSettledStatus error]
F -- throws SourceTextTooLargeError --> I[setSettledStatus error reason=too-large]
F -- throws other error --> J[console.error + setSettledStatus error]
subgraph fileSource.ts
K[readFsSpec] --> L{file.size > maxBytes?}
L -- yes --> M[throw SourceTextTooLargeError]
L -- no --> N[Bun.file.text]
O[readGitObjectSpec] --> P[git show subprocess]
P --> Q[readStreamTextWithLimit stdout]
Q --> R{totalBytes > maxBytes?}
R -- yes --> S[proc.kill + throw SourceTextTooLargeError]
R -- no --> T[accumulate chunks → decode]
end
E -.-> K
E -.-> O
|
| try { | ||
| output = await Promise.all([ | ||
| proc.exited, | ||
| new Response(proc.stdout).text(), | ||
| new Response(proc.stderr).text(), | ||
| readStreamTextWithLimit(proc.stdout, maxSourceBytes, () => proc.kill()), | ||
| readStreamTextWithLimit(proc.stderr, 64 * 1024), | ||
| ]); | ||
| } catch (error) { | ||
| if (error instanceof SourceTextTooLargeError) { | ||
| proc.kill(); | ||
| await proc.exited.catch(() => undefined); | ||
| throw error; | ||
| } | ||
|
|
||
| logSourceDiagnostic(`failed to collect Git source ${objectName}`, error); | ||
| return null; | ||
| } |
There was a problem hiding this comment.
SourceTextTooLargeError from stderr reader surfaces as wrong UI message
Both stdout and stderr reads share the same SourceTextTooLargeError type, and the catch block re-throws any instance of it without distinguishing which stream originated it. If git show writes more than 64 KB to stderr (e.g., hook output, verbose trace logging), the error from the stderr readStreamTextWithLimit call will be caught and re-thrown, causing the caller to display "Source too large to expand" even though the actual source content may have been well within the 1 MB limit. The stderr overflow should instead be treated as a generic read failure (logged and return null) rather than mapped to SourceTextTooLargeError.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/core/fileSource.ts
Line: 186-201
Comment:
**`SourceTextTooLargeError` from stderr reader surfaces as wrong UI message**
Both stdout and stderr reads share the same `SourceTextTooLargeError` type, and the catch block re-throws any instance of it without distinguishing which stream originated it. If `git show` writes more than 64 KB to stderr (e.g., hook output, verbose trace logging), the error from the stderr `readStreamTextWithLimit` call will be caught and re-thrown, causing the caller to display "Source too large to expand" even though the actual source content may have been well within the 1 MB limit. The stderr overflow should instead be treated as a generic read failure (logged and return `null`) rather than mapped to `SourceTextTooLargeError`.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Good catch — fixed. Oversized stderr now creates a generic diagnostics-limit error instead of SourceTextTooLargeError, so the UI only shows “Source too large…” for over-limit source stdout. I also added a regression test for oversized git stderr returning a generic source failure.
This comment was generated by Pi using OpenAI GPT-5
c438eb3 to
63443a6
Compare
Summary
git showsource reads while streaming instead of buffering the whole blobTest plan
bun test src/core/fileSource.test.ts src/core/loaders.test.ts src/ui/diff/expandCollapsedRows.test.ts src/ui/hooks/useReviewController.test.tsxbun run typecheckThis PR description was generated by Pi using OpenAI GPT-5