HealthLog version
1.37.11 (build ca88d8c1a9cb)
Deployment type
Self-hosted (Docker)
What happened?
A mixed set of 18 documents was uploaded: 17 PDFs and one JPEG. With ChatGPT Account (Codex OAuth) connected and automatic AI document reading enabled, HealthLog successfully generated an individual AI summary for every document. This confirms that authentication, AI consent, image input and the server-side PDF rasterisation path were working.
Running Index all for search indexed the JPEG but repeatedly left all 17 PDFs without a content index.
The v1.37.11 batch code in src/lib/jobs/document-content-index-backfill.ts builds its candidate MIME list from pick.pdfSupported. The Codex provider supports image input rather than native PDF input, so PDFs are filtered out before prepareVisionInput() can use the existing PDF-to-image path.
Expected behavior
Index all for search should accept a PDF when either:
- the selected provider supports PDFs natively; or
- HealthLog can rasterise the PDF and the provider supports image input.
The batch result should separately report indexed, skipped and failed documents, and rerunning it should remain idempotent.
Steps to reproduce
- Connect ChatGPT Account (Codex) as the AI provider.
- Enable document AI consent.
- Upload at least one JPEG and one PDF.
- Confirm that Read with AI or automatic AI reading can summarise the PDF successfully.
- Open the Documents page and run Index all for search.
- Observe that the JPEG gains a content index while the PDF remains unindexed.
- Run the batch again and observe the same result.
Workaround used
Temporarily disable Read documents automatically with AI, open each unindexed PDF, and run Read with AI manually. This successfully read the tested PDF and changed the action to Read again, but it is a repetitive document-by-document workaround and does not repair the batch operation.
The workaround is also constrained by HealthLog's shared six-per-hour document-AI limit described below. Manually reading 17 PDFs therefore requires at least three separate allowance windows, and using Suggest details, Summarise, Show extracted text, structured extraction or another manual indexing action can consume the same allowance.
Additional finding: the six-per-hour limit is imposed by HealthLog
Investigation after filing confirmed that this is an application-owned limit, not a Docker, Apple or OpenAI/Codex rate limit.
In v1.37.11:
src/lib/documents/ai-route-support.ts hard-codes DOCUMENT_AI_LIMIT_PER_HOUR = 6 and a one-hour window.
- Index, suggest and summary routes use the shared
documents-inbound:<userId> bucket.
- The structured document-extraction route uses the same bucket and the same six/hour values.
- The gate runs before the provider call, so it applies regardless of whether the selected provider is Codex, a BYO API key or another provider.
- The values are not exposed as an environment or admin setting.
- The API sends
X-RateLimit-Remaining and X-RateLimit-Reset, but the user-facing message only says Too many AI requests — try again in a few minutes. Depending on when the first request opened the bucket, the actual wait can be much longer than a few minutes.
- Some routes check the bucket before input preparation, so a request that fails before provider dispatch can still consume an allowance slot.
The limit itself appears intentional as a cost and abuse safeguard. The usability problem is that it is shared across several visible actions, not explained before the user starts a multi-document workflow, not configurable for a personal self-hosted instance, and does not expose the reset time in the UI.
Possible solution
- Build the candidate MIME list from effective transform capability: native PDF support or server PDF rasterisation plus provider image support.
- Allow
prepareVisionInput() to rasterise PDFs for Codex instead of excluding them before that function runs.
- Return per-document terminal outcomes and separate batch counts for indexed, skipped and failed.
- Preserve idempotent reruns so existing content-index rows are not duplicated.
- Add tests for a mixed JPEG, text-layer PDF and scanned PDF corpus with
CHATGPT_OAUTH.
- Display the shared remaining allowance and exact reset time using the rate-limit headers already returned by the API.
- Explain which actions share the document-AI allowance before a bulk workflow starts.
- Consider an operator-configurable limit for self-hosted instances while retaining six/hour as the safe default.
- Avoid consuming a slot until a provider call is actually attempted, or provide equivalent handling for pre-provider failures.
Relevant logs / screenshots
No document contents or private screenshots are attached. The safe observed result was one JPEG indexed and 17 PDFs still unindexed after repeated batch runs. The UI also displayed the generic AI rate-limit message after the shared allowance was exhausted.
Browser / OS (if applicable)
HealthLog web app on macOS 27 arm64.
Pre-flight checks
HealthLog version
1.37.11 (build
ca88d8c1a9cb)Deployment type
Self-hosted (Docker)
What happened?
A mixed set of 18 documents was uploaded: 17 PDFs and one JPEG. With ChatGPT Account (Codex OAuth) connected and automatic AI document reading enabled, HealthLog successfully generated an individual AI summary for every document. This confirms that authentication, AI consent, image input and the server-side PDF rasterisation path were working.
Running Index all for search indexed the JPEG but repeatedly left all 17 PDFs without a content index.
The v1.37.11 batch code in
src/lib/jobs/document-content-index-backfill.tsbuilds its candidate MIME list frompick.pdfSupported. The Codex provider supports image input rather than native PDF input, so PDFs are filtered out beforeprepareVisionInput()can use the existing PDF-to-image path.Expected behavior
Index all for search should accept a PDF when either:
The batch result should separately report indexed, skipped and failed documents, and rerunning it should remain idempotent.
Steps to reproduce
Workaround used
Temporarily disable Read documents automatically with AI, open each unindexed PDF, and run Read with AI manually. This successfully read the tested PDF and changed the action to Read again, but it is a repetitive document-by-document workaround and does not repair the batch operation.
The workaround is also constrained by HealthLog's shared six-per-hour document-AI limit described below. Manually reading 17 PDFs therefore requires at least three separate allowance windows, and using Suggest details, Summarise, Show extracted text, structured extraction or another manual indexing action can consume the same allowance.
Additional finding: the six-per-hour limit is imposed by HealthLog
Investigation after filing confirmed that this is an application-owned limit, not a Docker, Apple or OpenAI/Codex rate limit.
In v1.37.11:
src/lib/documents/ai-route-support.tshard-codesDOCUMENT_AI_LIMIT_PER_HOUR = 6and a one-hour window.documents-inbound:<userId>bucket.X-RateLimit-RemainingandX-RateLimit-Reset, but the user-facing message only says Too many AI requests — try again in a few minutes. Depending on when the first request opened the bucket, the actual wait can be much longer than a few minutes.The limit itself appears intentional as a cost and abuse safeguard. The usability problem is that it is shared across several visible actions, not explained before the user starts a multi-document workflow, not configurable for a personal self-hosted instance, and does not expose the reset time in the UI.
Possible solution
prepareVisionInput()to rasterise PDFs for Codex instead of excluding them before that function runs.CHATGPT_OAUTH.Relevant logs / screenshots
No document contents or private screenshots are attached. The safe observed result was one JPEG indexed and 17 PDFs still unindexed after repeated batch runs. The UI also displayed the generic AI rate-limit message after the shared allowance was exhausted.
Browser / OS (if applicable)
HealthLog web app on macOS 27 arm64.
Pre-flight checks