{"record":{"id":"9deeb2ea03741839","repo":"deepset-ai/haystack","slug":"pipeline-was-cancelled-no-result-available","errorCode":null,"errorMessage":"Pipeline was cancelled; no result available.","messagePattern":"Pipeline was cancelled; no result available\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"haystack/core/pipeline/pipeline.py","lineNumber":100,"sourceCode":"                    return\n                yield cast(StreamingChunk, item)  # at this point, item is guaranteed to be a StreamingChunk\n\n        finally:\n            if self._cancel_on_abandon:\n                await self.aclose()\n\n    @property\n    def result(self) -> dict[str, Any]:\n        \"\"\"\n        Final pipeline output dict, available only after a successful, complete run.\n\n        Raises a `RuntimeError` if the pipeline has not finished or was cancelled. If the pipeline failed, re-raises the\n        original exception.\n        \"\"\"\n        if not self._task.done():\n            raise RuntimeError(\"Pipeline has not finished; iterate the handle first.\")\n        if self._task.cancelled():\n            raise RuntimeError(\"Pipeline was cancelled; no result available.\")\n        exc = self._task.exception()\n        if exc is not None:\n            raise exc\n        return self._task.result()\n\n    async def aclose(self) -> None:\n        \"\"\"\n        Cancel the underlying pipeline task.\n\n        Bounded by `_CLEANUP_TIMEOUT_SECONDS` so that components cannot block cleanup indefinitely.\n        \"\"\"\n        if not self._task.done():\n            self._task.cancel()\n            with contextlib.suppress(BaseException):\n                await asyncio.wait_for(self._task, timeout=self._CLEANUP_TIMEOUT_SECONDS)\n\n\nclass Pipeline(PipelineBase):","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/core/pipeline/pipeline.py#L82-L118","documentation":"Pipeline.result() raises RuntimeError if the pipeline's asyncio task was cancelled before completion, because there is no final output to return. This is distinct from a failed run (which re-raises the original exception).","triggerScenarios":"Cancelling the run (e.g., asyncio.Task.cancel(), cancellation of the surrounding coroutine, timeout, KeyboardInterrupt in async context) and then calling result().","commonSituations":"asyncio.wait_for timeouts cancelling the pipeline task, user-initiated shutdown, pipeline.aclose() during a run, or cancellation propagated from a parent task.","solutions":["Guard result() access with a check whether the task was cancelled before calling it","Wrap result() in try/except RuntimeError and treat it as a cancelled run","Avoid cancelling the pipeline task if the final result is needed; or re-run the pipeline"],"exampleFix":"// before\nprint(handle.result())\n// after\ntry:\n    print(handle.result())\nexcept RuntimeError:\n    logger.warning(\"Pipeline run was cancelled; no result available.\")","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"def was_cancelled(pipeline) -> bool:\n    task = getattr(pipeline, \"_task\", None)\n    return task is not None and task.cancelled()","tryCatchPattern":"try:\n    result = handle.result()\nexcept RuntimeError as e:\n    if \"cancelled\" in str(e):\n        logger.warning(\"Run cancelled; re-running or aborting\")\n    else:\n        raise","preventionTips":["Avoid cancelling tasks whose results you need; use cooperative cancellation flags","Account for asyncio.wait_for timeouts cancelling the run","Call aclose()/cleanup deliberately and re-run if the result is required"],"tags":["python","asyncio","cancellation","pipeline"],"backgroundTag":"task-cancelled","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}