can1357/oh-my-pi · error · RpcConcurrencyError
Cannot start {operation} while {self.active_operation} is al
Error message
Cannot start {operation} while {self.active_operation} is already collecting prompt lifecycle events What it means
The client serializes prompt lifecycle event collection: a per-client guard ensures only one operation at a time collects events. acquire() raises RpcConcurrencyError if you start a second operation (e.g. a second prompt) while the first is still active.
Source
Thrown at python/omp-rpc/src/omp_rpc/client.py:430
def current_index(self) -> int:
return self.offset + len(self.items)
def snapshot(self) -> tuple[THistoryItem, ...]:
return tuple(self.items)
def snapshot_from(self, start_index: int) -> tuple[THistoryItem, ...]:
return tuple(self.items[start_index - self.offset :])
@dataclass(slots=True)
class _PromptLifecycleCoordinator:
lock: threading.Lock = field(default_factory=threading.Lock)
active_operation: str | None = None
def acquire(self, operation: str) -> None:
with self.lock:
if self.active_operation is not None:
raise RpcConcurrencyError(
f"Cannot start {operation} while {self.active_operation} is already collecting prompt lifecycle events"
)
self.active_operation = operation
def release(self, operation: str) -> None:
with self.lock:
if self.active_operation == operation:
self.active_operation = None
class RpcClient:
def __init__(
self,
*,
command: Sequence[str] | None = None,
executable: str = "omp",
provider: str | None = None,
model: str | None = None,View on GitHub (pinned to 9690622007)
Solutions
- Await/complete the first prompt before starting the next on the same client.
- Create a separate RpcClient (separate agent subprocess) per concurrent operation.
- Serialize prompts with an asyncio.Lock or queue around client.prompt() calls.
- Check for un-awaited coroutines or background tasks issuing prompts concurrently.
Example fix
# before: concurrent prompts on one client
tasks = [client.prompt(t) for t in prompts]
results = await asyncio.gather(*tasks)
# after: serialize, or one client per prompt
results = []
for t in prompts:
results.append(await client.prompt(t)) Defensive patterns
Strategy: try-catch
Try / catch
prompt_lock = threading.Lock()
with prompt_lock:
result = client.prompt(text) # serialize lifecycle-collecting ops
# or:
try:
result = await client.prompt(text)
except RpcConcurrencyError as exc:
logger.error("another prompt is active on this client: %s", exc) Prevention
- Never share one RpcClient across concurrent tasks/threads
- Await each prompt before starting the next
- Use one client per concurrent operation or a locking queue
When it happens
Trigger: Calling client.prompt() (or another lifecycle-collecting operation) while a previous prompt is still running on the same RpcClient instance — e.g. concurrent tasks sharing one client, or not awaiting the first prompt before starting another.
Common situations: Asyncio tasks or threads sharing a single RpcClient; fire-and-forget prompts without await; retry logic that issues a new prompt while the old one is still completing.
Related errors
- Client already started
- Client not started
- RPC message snapshot does not match current messages
- Agent "${resolvedAgentId}" is already owned by another sessi
- Vibe parent session changed before mode exit could be persis
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/7059ad5d7267de5a.
Report an issue: GitHub.