{"record":{"id":"a16776a79dea9bb0","repo":"sgl-project/sglang","slug":"encoder-request-was-released-state-req-id","errorCode":null,"errorMessage":"Encoder request was released: {state.req_id}","messagePattern":"Encoder request was released: (.+?)","errorType":"http","errorClass":"InternalError","httpStatus":500,"severity":"error","filePath":"python/sglang/srt/disaggregation/encoder/server.py","lineNumber":680,"sourceCode":"            )\n        state.embedding_data = mm_data\n        state.embedding_ready.set()\n\n    async def _wait_for_embedding(self, state: ReqState) -> EmbeddingData:\n        await state.embedding_ready.wait()\n        if state.embedding_data is None:\n            raise InternalError(f\"No embedding available for request: {state.req_id}\")\n        return state.embedding_data\n\n    async def send_to_destination(\n        self, state: ReqState, destination: SendDestination\n    ) -> None:\n        async with state.lifecycle_condition:\n            if (\n                self.req_states.get(state.req_id) is not state\n                or state.release_requested\n            ):\n                raise InternalError(f\"Encoder request was released: {state.req_id}\")\n            state.active_sends += 1\n        try:\n            await self.delivery.send(state, destination)\n        finally:\n            async with state.lifecycle_condition:\n                state.active_sends -= 1\n                state.lifecycle_condition.notify_all()\n\n    async def release_request(\n        self, req_id: str, *, preserve_metadata: bool = False\n    ) -> None:\n        \"\"\"Release backend resources, then the embedding, through one path.\"\"\"\n        state = self.req_states.get(req_id)\n        if state is None:\n            if not preserve_metadata:\n                await meta_registry.discard(req_id)\n            return\n        async with state.lifecycle_condition:","sourceCodeStart":662,"sourceCodeEnd":698,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/disaggregation/encoder/server.py#L662-L698","documentation":"send_to_destination checks under the request's lifecycle lock that the ReqState is still the live entry in req_states and has not been release-requested; if the request was concurrently released, it raises InternalError to prevent sending an embedding whose buffers may be recycled.","triggerScenarios":"A release_request (timeout, client abort, or sweep) racing with an in-flight send; calling send/send_with_url/run for a req_id that was already released by another coroutine or the periodic sweep.","commonSituations":"Client timeout triggering release while a slow transfer is queued; duplicate lifecycle management where two owners both release; long-running sends outliving the request TTL.","solutions":["Ensure only one component owns release for a request; do not manually release while sends are pending","Tune request TTL / sweep interval so sends complete before release","Retry the whole request with a fresh req_id if the send was aborted mid-flight","Check logs for what triggered the concurrent release (timeout vs abort vs sweep)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if encoder.req_states.get(req_id) is not state or state.release_requested:\n    abort_send(req_id)","typeGuard":null,"tryCatchPattern":"try:\n    await encoder.send_to_destination(state, dest)\nexcept InternalError as e:\n    if 'released' in str(e):\n        return  # request lifecycle ended; nothing to deliver\n    raise","preventionTips":["Single owner for release; never release while sends are pending","Tune TTL/sweep to outlast slowest transfer","Retry with a fresh req_id rather than resurrecting a released one"],"tags":["lifecycle","race-condition","encoder","send"],"backgroundTag":"request-already-released","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}