{"record":{"id":"f026b89f18b46b4e","repo":"cocoindex-io/cocoindex","slug":"watch-is-not-supported-when-preview-true","errorCode":null,"errorMessage":"watch() is not supported when preview=True","messagePattern":"watch\\(\\) is not supported when preview=True","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/_internal/app.py","lineNumber":105,"sourceCode":"        if self._core_handle is None:\n            return None\n        return self._snapshot_from_handle(self._core_handle).stats\n\n    async def watch(self) -> AsyncIterator[UpdateSnapshot[R]]:\n        \"\"\"Async iterator that yields progress snapshots.\n\n        Yields UpdateSnapshot with status:\n        - RUNNING while the update is in progress (not yet ready)\n        - READY when the root component is ready (initial processing caught up)\n\n        In live mode, after the initial READY, continues yielding RUNNING snapshots\n        as stats update from incremental processing. When terminated, yields a final\n        READY snapshot with the result set.\n\n        On error, raises the exception directly from the iterator.\n        \"\"\"\n        if self._preview:\n            raise TypeError(\"watch() is not supported when preview=True\")\n        handle = await self._ensure_started()\n        last_version = 0\n        while True:\n            version = await handle.changed()\n\n            # Check termination before dedup — notify_terminated() sends\n            # TERMINATED_VERSION on the watch channel without updating the\n            # stats version, so the dedup check would skip it.\n            if version >= _TERMINATED_VERSION:\n                snap = self._snapshot_from_handle(handle)\n                pyvalue: Any = await handle.result()\n                result: R = pyvalue.get(fn_ret_deserializer(self._main_fn))\n                if snap.stats is not None:\n                    yield UpdateSnapshot(\n                        stats=snap.stats, status=UpdateStatus.READY, result=result\n                    )\n                return\n","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/_internal/app.py#L87-L123","documentation":"App.watch() streams live progress updates as incremental processing happens. When the App was configured with preview=True it runs a one-shot preview and produces no continuous change stream, so watch() is meaningless and raises TypeError.","triggerScenarios":"Calling app.watch() (directly or via _drive_to_ready) on an App constructed with coco.AppConfig(..., preview=True) or preview=True passed to the App.","commonSituations":"Reusing a preview-mode App for a long-running watcher; toggling preview on for debugging and forgetting it before adding watch(); copying example watch() code into a preview app.","solutions":["Set preview=False in the App config, then call watch()","For preview runs, await app.update() and read the final snapshot instead of watching","Create a separate non-preview App instance for watching"],"exampleFix":"// before\napp = coco.App(coco.AppConfig(name=\"demo\", preview=True), main)\nasync for snap in app.watch(): ...\n// after\napp = coco.App(coco.AppConfig(name=\"demo\"), main)\nasync for snap in app.watch(): ...","handlingStrategy":"validation","validationCode":"if not app._preview:\n    async for snap in app.watch():\n        ...\nelse:\n    await app.update()  # preview: one-shot only","typeGuard":"def supports_watch(app) -> bool:\n    return not getattr(app, \"_preview\", False)","tryCatchPattern":"try:\n    async for snap in app.watch():\n        ...\nexcept TypeError as e:\n    if \"preview=True\" in str(e):\n        await app.update()  # fall back to one-shot preview result","preventionTips":["Only call watch() on non-preview Apps","If preview and watch are both needed, build two App instances with different configs"],"tags":["python","api-misuse","preview"],"backgroundTag":"unsupported-operation","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}