cocoindex-io/cocoindex · error · RuntimeError
coco.use_state() cannot be called inside a `with coco.compon
Error message
coco.use_state() cannot be called inside a `with coco.component_subpath()` block
What it means
use_state() attaches state to the current processing component's stable path. Inside a `with coco.component_subpath()` block the ambient path is temporarily re-routed, so state would be keyed to the wrong path; the API detects this mismatch and refuses.
Source
Thrown at python/cocoindex/_internal/api.py:862
Example::
# Plain (value typed as Any)
counter = coco.use_state("counter", 0)
# Typed — handle.value is Cursor, with full type inference
@dataclass
class Cursor:
pos: int
tag: str
cur = coco.use_state("cursor", type_hint=Cursor, initial_value=Cursor(0, "init"))
cur.value.pos += 1
cur.value = Cursor(cur.value.pos, "next")
"""
ctx = get_context_from_ctx()
if ctx._core_path != ctx._core_processor_ctx.stable_path:
raise RuntimeError(
"coco.use_state() cannot be called inside a `with coco.component_subpath()` block"
)
if ctx._in_memo_fn:
raise RuntimeError(
"coco.use_state() cannot be called inside a memoized function"
)
try:
# initial_value passed unserialized; engine core drops it if a value is
# already stored on the previous run for this key.
stored = ctx._core_processor_ctx.use_state(key, initial_value)
except ValueError as e:
# Rust client errors surface as ValueError; normalize to RuntimeError so
# all use_state usage errors have a consistent type for callers.
raise RuntimeError(str(e)) from None
if type_hint is not None:
deserializer = get_deserialize_fn(
type_hint, # type: ignore[arg-type] # type objects are hashable at runtimeView on GitHub (pinned to e84aa99b32)
Solutions
- Move the coco.use_state() call outside the `with coco.component_subpath()` block
- If state is needed for the nested subpath, mount it as its own component (use_mount/mount) and call use_state within that component
Example fix
// before
with coco.component_subpath("phase"):
cur = coco.use_state("cursor", initial_value=Cursor(0, "init"))
// after
cur = coco.use_state("cursor", initial_value=Cursor(0, "init"))
with coco.component_subpath("phase"):
... Defensive patterns
Strategy: validation
Validate before calling
# call use_state before entering any component_subpath block
state = coco.use_state("cursor", initial_value=Cursor(0, "init"))
with coco.component_subpath("phase"):
... # no use_state here Try / catch
try:
cur = coco.use_state("cursor", initial_value=Cursor(0, "init"))
except RuntimeError as e:
if "component_subpath()" in str(e):
raise # restructure: move use_state outside the with-block Prevention
- Treat use_state as component-body-only code, never inside subpath blocks
- Keep state initialization at the top of the component body before any with-blocks
When it happens
Trigger: Calling coco.use_state(...) on the current component context while inside a `with coco.component_subpath(...):` block, where ctx._core_path differs from the processor's stable_path.
Common situations: Wrapping a section of a component body in component_subpath() to namespace nested mounts, and accidentally calling use_state() inside that block; reworking code that moved use_state inside the with-block during refactoring.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- use_mount() requires a ComponentSubpath when the function ha
- LiveComponent classes cannot be used with use_mount(). Use m
- mount() requires a ComponentSubpath when the function has no
- mount_each() requires a ComponentSubpath when the function h
- Cannot use sync 'with coco.runtime()' from within an async e
AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08).
Data as JSON: /api/errors/40f05f0a25bdf5ec.
Report an issue: GitHub.