refactor(pdf): move document extraction to plugin#71278
Conversation
Greptile SummaryThis PR moves PDF extraction out of core into a bundled
Confidence Score: 4/5Safe to merge after addressing the error-swallowing regression that turns real extraction failures into a misleading 'disabled' message. One P1 finding: the catch { continue; } in the extractor dispatch loop is a behavioral regression — real document-level errors from pdfjs are now silently absorbed and reported as 'extraction disabled or unavailable' instead of the actual cause. This is a present defect on the changed path that will make debugging extraction failures significantly harder. The P2 (unguarded factory call) is a hardening gap that compounds the same symptom. src/media/document-extractors.runtime.ts (error swallowing in extractor dispatch loop), src/plugins/document-extractor-public-artifacts.ts (unguarded factory invocation) Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/media/document-extractors.runtime.ts
Line: 51-61
Comment:
**Extraction errors silently swallowed, producing misleading failure message**
When an extractor's `extract()` call throws — for example pdfjs encountering a malformed or password-protected PDF — the `catch { continue; }` block discards the error and moves to the next extractor. With only one extractor registered, all extractors are skipped, `extractDocumentContent` returns `null`, and `extractPdfContent` re-raises "PDF extraction disabled or unavailable". This is factually incorrect: the extractor is enabled and reachable; it failed because of the document itself. The previous code let pdfjs errors propagate to the caller directly, giving a meaningful stack trace. At minimum the caught error should be surfaced (e.g., logged or re-thrown when no subsequent extractor succeeds).
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: src/plugins/document-extractor-public-artifacts.ts
Line: 66-69
Comment:
**Uncaught exception from factory function causes entire extractor loading to fail**
`exported()` is called without a try/catch. If a `create*DocumentExtractor` factory throws (e.g., a plugin that probes for native dependencies at construction time), the exception propagates out of `collectExtractorFactories` → `loadBundledDocumentExtractorEntriesFromDir` → `resolvePluginDocumentExtractors`, which is then absorbed by the `catch { return null; }` in `extractDocumentContent`. The end result is the same misleading "disabled or unavailable" error, and a factory bug in one plugin silently disables all extractors in that module. Wrapping the `exported()` call in its own try/catch and skipping (or logging) failing factories would isolate the blast radius.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "refactor(pdf): move document extraction ..." | Re-trigger Greptile |
| try { | ||
| const result = await extractor.extract(params); | ||
| if (result) { | ||
| return { | ||
| ...result, | ||
| extractor: extractor.id, | ||
| }; | ||
| } | ||
| } catch { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Extraction errors silently swallowed, producing misleading failure message
When an extractor's extract() call throws — for example pdfjs encountering a malformed or password-protected PDF — the catch { continue; } block discards the error and moves to the next extractor. With only one extractor registered, all extractors are skipped, extractDocumentContent returns null, and extractPdfContent re-raises "PDF extraction disabled or unavailable". This is factually incorrect: the extractor is enabled and reachable; it failed because of the document itself. The previous code let pdfjs errors propagate to the caller directly, giving a meaningful stack trace. At minimum the caught error should be surfaced (e.g., logged or re-thrown when no subsequent extractor succeeds).
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/media/document-extractors.runtime.ts
Line: 51-61
Comment:
**Extraction errors silently swallowed, producing misleading failure message**
When an extractor's `extract()` call throws — for example pdfjs encountering a malformed or password-protected PDF — the `catch { continue; }` block discards the error and moves to the next extractor. With only one extractor registered, all extractors are skipped, `extractDocumentContent` returns `null`, and `extractPdfContent` re-raises "PDF extraction disabled or unavailable". This is factually incorrect: the extractor is enabled and reachable; it failed because of the document itself. The previous code let pdfjs errors propagate to the caller directly, giving a meaningful stack trace. At minimum the caught error should be surfaced (e.g., logged or re-thrown when no subsequent extractor succeeds).
How can I resolve this? If you propose a fix, please make it concise.| const candidate = exported(); | ||
| if (isDocumentExtractorPlugin(candidate)) { | ||
| extractors.push(candidate); | ||
| } |
There was a problem hiding this comment.
Uncaught exception from factory function causes entire extractor loading to fail
exported() is called without a try/catch. If a create*DocumentExtractor factory throws (e.g., a plugin that probes for native dependencies at construction time), the exception propagates out of collectExtractorFactories → loadBundledDocumentExtractorEntriesFromDir → resolvePluginDocumentExtractors, which is then absorbed by the catch { return null; } in extractDocumentContent. The end result is the same misleading "disabled or unavailable" error, and a factory bug in one plugin silently disables all extractors in that module. Wrapping the exported() call in its own try/catch and skipping (or logging) failing factories would isolate the blast radius.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugins/document-extractor-public-artifacts.ts
Line: 66-69
Comment:
**Uncaught exception from factory function causes entire extractor loading to fail**
`exported()` is called without a try/catch. If a `create*DocumentExtractor` factory throws (e.g., a plugin that probes for native dependencies at construction time), the exception propagates out of `collectExtractorFactories` → `loadBundledDocumentExtractorEntriesFromDir` → `resolvePluginDocumentExtractors`, which is then absorbed by the `catch { return null; }` in `extractDocumentContent`. The end result is the same misleading "disabled or unavailable" error, and a factory bug in one plugin silently disables all extractors in that module. Wrapping the `exported()` call in its own try/catch and skipping (or logging) failing factories would isolate the blast radius.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a78335602d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } catch { | ||
| continue; |
There was a problem hiding this comment.
Propagate extractor failures for matching MIME handlers
When a matching document extractor throws (for example, a malformed/corrupt PDF in extractor.extract), this catch swallows the error and falls through as if no extractor existed; extractPdfContent then rethrows a generic "disabled or unavailable" message. That regresses diagnostics compared with the previous direct PDF.js path, because real parsing/runtime failures are now misreported as plugin disablement, making operator triage and user error handling inaccurate.
Useful? React with 👍 / 👎.
c885d2b to
5c89266
Compare
5c89266 to
2273737
Compare
Summary
document-extractplugin that owns local PDF extraction andpdfjs-distWhy
This continues the SBOM dependency-risk split by moving PDF parsing out of core while preserving default PDF extraction behavior through an enabled bundled plugin.
Tests
pnpm plugin-sdk:api:checkpnpm deps:root-ownership:check && pnpm deps:sbom-risk:checkpnpm test src/media/pdf-extract.test.ts src/plugins/document-extractors.runtime.test.ts extensions/document-extract/document-extractor.test.ts src/agents/tools/pdf-tool.test.ts src/media/input-files.fetch-guard.test.tspnpm test:extension document-extractpnpm exec tsgo -p tsconfig.core.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core-pdf-document-extract-postrebase.tsbuildinfopnpm buildpnpm test:build:bundled-runtime-depsNote: direct
pnpm exec tsgo -p tsconfig.extensions.json ...still hits the pre-existingextensions/qa-lab/web/src/main.tsCSS side-effect import declaration issue on this checkout.