{"record":{"id":"22e0523c60f7204c","repo":"iflytek/astron-agent","slug":"23901-conversation-is-running-please-do-not-resume","errorCode":"23901","errorMessage":"Conversation is running, please do not resume repeatedly","messagePattern":"Conversation is running, please do not resume repeatedly","errorType":"error_code","errorClass":"CustomException","httpStatus":null,"severity":"error","filePath":"core/workflow/api/v1/chat/open.py","lineNumber":131,"sourceCode":"    event_id = request.event_id\n    event_type = request.event_type\n    content = request.content\n    span = Span(app_id=\"\", uid=\"\", chat_id=\"\")\n    m = Meter()\n\n    with span.start(\n        attributes={\"event_id\": event_id},\n    ) as span_context:\n\n        try:\n            event: Optional[Event] = EventRegistry().get_event(event_id=event_id)\n            if event is None:\n                raise CustomException(\n                    CodeEnum.EVENT_REGISTRY_NOT_FOUND_ERROR,\n                    \"Event not found\",\n                )\n            if EventRegistry().check_event_lock(event_id=event_id):\n                raise CustomException(CodeEnum.EVENT_REGISTRY_LOCK_ERROR)\n            EventRegistry().lock_event(event_id=event_id, sid=span.sid)\n\n            m.set_label(\"flow_id\", event.flow_id)\n            m.set_label(\"app_id\", event.app_id)\n\n            span.set_attribute(\"flow_id\", event.flow_id)\n            span.app_id = event.app_id\n            span.uid = event.uid\n            span.chat_id = event.chat_id\n\n            await span_context.add_info_events_async(\n                {\"resume_event\": json.dumps(event.dict(), ensure_ascii=False)}\n            )\n\n            if not event.status == ChatStatus.INTERRUPT.value:\n                raise CustomException(\n                    CodeEnum.EVENT_REGISTRY_NOT_FOUND_ERROR,\n                    \"Current event is not paused\",","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/workflow/api/v1/chat/open.py#L113-L149","documentation":"Raised by resume_open when EventRegistry().check_event_lock(event_id) is true, i.e. another request (span sid) already holds the lock for this event and it is currently being processed. The lock prevents concurrent resumes of the same conversation; a second resume attempt fails with code 23901 (EVENT_REGISTRY_LOCK_ERROR).","triggerScenarios":"Two resume calls racing on the same event_id (double-click, retry timeout, parallel tabs); a previous resume still running/streaming its response while the client reissues resume.","commonSituations":"User clicks 'continue' repeatedly in the UI; HTTP client retries after a slow first resume; frontend ignores the still-open SSE stream and fires another resume; background job and user request both resume the same event.","solutions":["Check the conversation state client-side and disable the resume action while a resume/stream is in flight.","Wait for the running resume to finish (consume the SSE stream to completion) before retrying.","Implement client-side deduplication/idempotency so only one resume request per event is sent.","If a lock is stuck (holder crashed), wait for lock expiry or clear it via unlock_event once the holder is confirmed dead."],"exampleFix":"# before\nawait Promise.all([resume_open(event_id), resume_open(event_id)])\n\n# after\nif (!resumingRef.current) {\n  resumingRef.current = true\n  try {\n    await resume_open(event_id)\n  } finally {\n    resumingRef.current = false\n  }\n}","handlingStrategy":"retry","validationCode":"if EventRegistry().check_event_lock(event_id=event_id):\n    raise RuntimeError(f\"event {event_id} is locked; resume already in progress\")","typeGuard":"def is_unlocked(event_id: str) -> bool:\n    return not EventRegistry().check_event_lock(event_id=event_id)","tryCatchPattern":"try:\n    await resume_open(event_id=event_id)\nexcept CustomException as e:\n    if e.code == CodeEnum.EVENT_REGISTRY_LOCK_ERROR.code:\n        await asyncio.sleep(backoff)\n        # retry once, or surface 'resume in progress' to the user\n    else:\n        raise","preventionTips":["Disable the resume button while a resume/stream is active","Use idempotency keys or client-side in-flight guards to prevent duplicate resumes","Consume the SSE stream to completion before allowing further interaction"],"tags":["concurrency","locking","workflow","race-condition"],"backgroundTag":"lock-contention","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}