{"record":{"id":"f14c15adb3646e3e","repo":"cocoindex-io/cocoindex","slug":"api-name-is-not-allowed-inside-process-live-u","errorCode":null,"errorMessage":"{api_name}() is not allowed inside process_live; use operator.update / operator.delete instead. (See specs/live_component/requirement.md for the rationale.)","messagePattern":"(.+?)\\(\\) is not allowed inside process_live; use operator\\.update / operator\\.delete instead\\. \\(See specs/live_component/requirement\\.md for the rationale\\.\\)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/_internal/live_component.py","lineNumber":93,"sourceCode":"#   inheritance chain holds. Future-proofing: integration tests verify both:\n#     (a) `coco.mount(...)` directly inside `process_live` raises\n#     (b) `coco.mount(...)` inside `process()` of a live component does NOT raise\n#   If (a) silently stops raising, the wrapper isn't installed; if (b)\n#   starts raising, the symmetric reset isn't taking effect — both are\n#   load-bearing for the live-component installer machinery.\n_in_process_live: ContextVar[bool] = ContextVar(\"_in_process_live\", default=False)\n\n\ndef check_not_in_process_live(api_name: str) -> None:\n    \"\"\"Raise if called from inside `process_live`.\n\n    Called by `coco.mount`, `coco.mount_each`, `coco.use_mount` at entry.\n    Outside of `process_live`, `_in_process_live.get()` returns the\n    default `False` (e.g. inside `process()` after `update_full`'s\n    inline reset, or in any non-live-component context).\n    \"\"\"\n    if _in_process_live.get():\n        raise RuntimeError(\n            f\"{api_name}() is not allowed inside process_live; \"\n            f\"use operator.update / operator.delete instead. \"\n            f\"(See specs/live_component/requirement.md for the rationale.)\"\n        )\n\n\nasync def _process_live_wrapper(instance: Any, operator: LiveComponentOperator) -> None:\n    \"\"\"Wrap a `process_live` invocation to set `_in_process_live = True`\n    and detach the operator's controller on exit.\n\n    Used by `_mount_live_component` (api.py) and the LiveCompClass branch\n    of `LiveComponentOperator.update`.\n\n    Live components run independently from the parent update, so parent\n    cooperative deadlines do not apply to ``process_live`` or the\n    ``operator.update_full()`` calls it starts.\n\n    Save/restore the prior value rather than using `ContextVar.reset(token)`:","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/_internal/live_component.py#L75-L111","documentation":"Inside a process_live body, structural mount APIs (coco.mount, coco.mount_each, coco.use_mount) are forbidden: live components must express changes through operator.update / operator.delete. check_not_in_process_live is called at the entry of those APIs and raises RuntimeError when the process_live context variable is set.","triggerScenarios":"Calling coco.mount(...), coco.mount_each(...) or coco.use_mount(...) inside the async body passed to process_live.","commonSituations":"Porting an existing update()-style main function into a live component body without replacing mount calls with operator updates; mixing full-scan mounting with incremental live semantics in the same component.","solutions":["Replace mount/use_mount/mount_each inside process_live with operator.update / operator.delete on the live component operator.","Move one-time static mounting outside the process_live body (e.g. in the lifespan/setup).","Consult specs/live_component/requirement.md for the required live-component pattern."],"exampleFix":"// before\nasync def body(op):\n    await coco.mount(process_file, f, target)\n// after\nasync def body(op):\n    await op.update(key, fn, args)","handlingStrategy":"validation","validationCode":"from cocoindex._internal.live_component import _in_process_live\nif _in_process_live.get():\n    raise RuntimeError(\"use operator.update/delete inside process_live\")","typeGuard":null,"tryCatchPattern":"try:\n    await coco.mount(fn, *args)\nexcept RuntimeError as e:\n    if \"process_live\" in str(e):\n        await operator.update(key, fn, args)","preventionTips":["Inside process_live bodies, only use operator.update/operator.delete.","Do all static mounting during setup, not in live update bodies."],"tags":["python","live-component","forbidden-api"],"backgroundTag":"unsupported-operation","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}