Skip to content

Ingestion guide's AWS Textract recipe reads only the first GetDocumentTextDetection page and never checks JobStatus, silently truncating multi-page OCR text (F-W1-DOCS-TRAIN-13) #883

Open

Description

@cemililik

Wave 3 · group W3 Docs · highest severity Medium · 1 finding(s) · effort docs fix

Summary

The OCR recipe makes one get_document_text_detection call, writes the LINE blocks it returns and runs forgelm ingest on the result. Textract returns at most 1,000 blocks per call — PAGE, LINE and WORD blocks all count — plus a NextToken for the rest, so a typical multi-page scan is cut short with no error and the truncated text becomes training data.

Primary finding

F-W1-DOCS-TRAIN-13 — The Textract recipe silently truncates paginated OCR output

severity Medium · confidence high · checked against the AWS API reference

What happens. docs/guides/ingestion.md:634-650 (Turkish mirror docs/guides/ingestion-tr.md:652-668); the single call is at EN :644 / TR :662. The snippet never follows NextToken and never checks JobStatus, so a job that is still IN_PROGRESS, FAILED or only a PARTIAL_SUCCESS looks the same as a finished one. It also uses $JOB_ID without showing where it comes from: the start-document-text-detection call in step 2 does not capture the returned JobId.

Where.

Evidence (re-verified on 2026-10-09).

  • AWS Textract API reference, GetDocumentTextDetection: results are paginated; when a response includes NextToken, call the operation again with it to get the next set; MaxResults defaults to 1,000 (https://docs.aws.amazon.com/textract/latest/APIReference/API_GetDocumentTextDetection.html).
  • The source review ran the embedded snippet against a two-page stub client: it made one call, printed only the first page and exited normally.
  • Both guide pages are unchanged on development.

Recommended fix. Capture the job id (JOB_ID=$(aws textract start-document-text-detection … --query JobId --output text)), wait until JobStatus is no longer IN_PROGRESS (or point to AWS's polling / SNS pattern), stop with an error on FAILED, print a warning on PARTIAL_SUCCESS, and loop over NextToken so every page's LINE blocks are written in order before forgelm ingest runs.

Acceptance criteria

  • The recipe follows NextToken until it is absent and writes every LINE block in order.
  • A failed or still-running job stops the recipe before forgelm ingest; a partial success is reported.
  • The snippet shows where JOB_ID comes from.
  • Documentation listed above is corrected in English and in its Turkish mirror in the same PR.
  • The finding is resolved or explicitly closed with a reason.

Found by the September 2026 independent review of ForgeLM against commit cab2947 and re-verified against development at f94595f on 2026-10-09. Code links point at cab2947; line numbers may have moved since. Finding IDs (F-W1-…) are stable references for this backlog.

Activity

  1. added
    documentationImprovements or additions to documentation
    severity: mediumReal defect with limited reach or a workaround
    wave: 3Roadmap wave 3: medium severity, module sweeps
    source: review-2026-09Found by the September 2026 independent review
    on Oct 9, 2026
  2. cemililik commented on Oct 11, 2026

    @cemililik
    CollaboratorAuthor

    Where to start

    Thanks for taking a look. Please confirm the issue is unassigned and comment before starting so work does not overlap.

    Start with these files on development:

    Capture JobId from the start response, wait for SUCCEEDED, reject failed/partial jobs explicitly, and follow every NextToken before ingesting LINE text. Verify the example with a local stub returning IN_PROGRESS then two result pages and a failure case; AWS credentials/network must not be needed for verification. Follow the linked AWS API contract.

    Documentation recipe only; no new OCR backend or AWS dependency in ForgeLM.

    Run the focused tests:

    pytest tests/test_ingestion.py --no-cov

    Run these guards/checks as applicable to the changed files:

    ruff format --check tests/test_ingestion.py
    ruff check tests/test_ingestion.py
    python3 tools/check_bilingual_parity.py --strict
    python3 tools/check_bilingual_code_blocks.py --strict
    python3 tools/check_anchor_resolution.py --strict
    python3 tools/check_tr_links_prefer_mirror.py --strict
    python3 tools/check_usermanual_self_contained.py --strict
    python3 tools/check_usermanual_schema_drift.py --strict

    If user-facing documentation changes, update the existing Turkish mirror in the same PR; keep commands, code and terminal output in English and structurally aligned. English-only contributor standards need no new mirror.

    Open the PR against development with Fixes #883 once every finding is resolved or explicitly closed with a reason; use Refs #883 for partial work and list the resolved finding IDs.

  3. cemililik commented on Oct 17, 2026

    @cemililik
    CollaboratorAuthor

    Update — re-verified on development (0766e94). The recipe is unchanged.

    To save you a choice: treat PARTIAL_SUCCESS like FAILED — print the status and stop with
    a non-zero exit before forgelm ingest, because training data must not be silently
    incomplete. The step-2 comment that says polling is out of scope will no longer be true;
    reword it.

    No test file changes: the pytest/ruff lines above are only a sanity run. In the Turkish
    block you may keep the English comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationfirst-timers-onlyReserved for a contributor's very first pull requestgood first issueGood for newcomersseverity: mediumReal defect with limited reach or a workaroundsource: review-2026-09Found by the September 2026 independent reviewwave: 3Roadmap wave 3: medium severity, module sweeps

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions