{"record":{"id":"882eeb6856a9d432","repo":"infiniflow/ragflow","slug":"too-many-iterations-while-loading-jira-documents","errorCode":null,"errorMessage":"Too many iterations while loading Jira documents.","messagePattern":"Too many iterations while loading Jira documents\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"common/data_source/jira/connector.py","lineNumber":881,"sourceCode":"    checkpoint = connector.build_dummy_checkpoint()\n    iterations = 0\n\n    while checkpoint.has_more:\n        wrapper = CheckpointOutputWrapper[JiraCheckpoint]()\n        generator = wrapper(connector.load_from_checkpoint(start=start, end=end, checkpoint=checkpoint))\n\n        for document, failure, next_checkpoint in generator:\n            if failure is not None:\n                failure_message = getattr(failure, \"failure_message\", str(failure))\n                raise RuntimeError(f\"Failed to load Jira documents: {failure_message}\")\n            if document is not None:\n                yield document\n            if next_checkpoint is not None:\n                checkpoint = next_checkpoint\n\n        iterations += 1\n        if iterations > iteration_limit:\n            raise RuntimeError(\"Too many iterations while loading Jira documents.\")\n\n\ndef test_jira(\n    *,\n    base_url: str,\n    project_key: str | None = None,\n    jql_query: str | None = None,\n    credentials: dict[str, Any],\n    batch_size: int = INDEX_BATCH_SIZE,\n    start_ts: float | None = None,\n    end_ts: float | None = None,\n    connector_options: dict[str, Any] | None = None,\n) -> list[Document]:\n    \"\"\"Programmatic entry point that mirrors the CLI workflow.\"\"\"\n\n    connector_kwargs = connector_options.copy() if connector_options else {}\n    connector = JiraConnector(\n        jira_base_url=base_url,","sourceCodeStart":863,"sourceCodeEnd":899,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/common/data_source/jira/connector.py#L863-L899","documentation":"A RuntimeError raised by the test load helper when the pagination loop exceeds iteration_limit full passes without the checkpoint reaching has_more=False. It is an infinite-loop safeguard: each outer iteration should advance the Jira checkpoint (start_at offset / paginated cursor), and if it never terminates the helper assumes checkpoint advancement is broken.","triggerScenarios":"Driving load_from_checkpoint in the helper's while-loop where each pass returns a checkpoint whose has_more stays True forever — e.g. the Jira search returning the same page because start_at is not incremented, next_checkpoint never being yielded (so `checkpoint` is never replaced), or a checkpoint round-trip (model_validate_json) losing the offset.","commonSituations":"Checkpoint serialization bug after a model change dropping start_at; a mocked/stubbed jira_client in tests that always returns the same page; Jira server ignoring the startAt parameter; passing iteration_limit too low for very large projects (each outer loop = one checkpoint batch, not one page).","solutions":["Check whether iteration_limit is simply too small for the dataset — the limit counts outer checkpoint passes, so raise it for large projects.","Log checkpoint.start_at and has_more per iteration to confirm the offset actually advances; if frozen, inspect the connector's pagination logic and the checkpoint model fields.","If next_checkpoint is never yielded by the generator, fix that path — the helper only advances when next_checkpoint is not None.","For test stubs, make the fake client return has_more=False on the final page."],"exampleFix":"# before\ndocs = list(yield_jira_documents(connector, start, end))  # RuntimeError: Too many iterations\n\n# after\n# small dataset but default iteration_limit too low / or checkpoint frozen — debug first\nfrom copy import deepcopy\ncp = connector.build_dummy_checkpoint()\npasses = 0\nwhile cp.has_more:\n    for doc, failure, ncp in CheckpointOutputWrapper[JiraCheckpoint]()(connector.load_from_checkpoint(start=start, end=end, checkpoint=cp)):\n        ...\n        if ncp is not None:\n            cp = ncp\n    passes += 1\n    print(passes, cp.start_at, cp.has_more)  # verify offset advances","handlingStrategy":"validation","validationCode":"cp = connector.build_dummy_checkpoint()\nassert cp.has_more is not None  # checkpoint model intact before long runs","typeGuard":null,"tryCatchPattern":"try:\n    docs = list(yield_jira_documents(connector, start, end))\nexcept RuntimeError as exc:\n    if str(exc) != \"Too many iterations while loading Jira documents.\":\n        raise\n    # dump checkpoint state and raise a diagnostic","preventionTips":["Size iteration_limit to the dataset — it counts checkpoint passes, not pages.","When stubbing the Jira client in tests, guarantee the final page sets has_more=False.","Log checkpoint.start_at each pass in new pagination code to catch frozen offsets early."],"tags":["jira","pagination","checkpoint","infinite-loop-guard","testing"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}