{"record":{"id":"ed4b96021dfd9d41","repo":"sgl-project/sglang","slug":"finish-reason-message","errorCode":null,"errorMessage":"{finish_reason[\"message\"]}","messagePattern":"\\{finish_reason\\[\"message\"\\]\\}","errorType":"exception","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"python/sglang/srt/managers/tokenizer_manager.py","lineNumber":1665,"sourceCode":"            out[\"meta_info\"] = meta_info\n        return out\n\n    async def _handle_abort_finish_reason(\n        self,\n        out: dict,\n        state: ReqState,\n        is_stream: bool,\n    ) -> Optional[dict]:\n        \"\"\"Returns the output dict to yield (stream abort), None for normal flow;\n        raises ValueError/HTTPException for non-stream aborts.\"\"\"\n        finish_reason = out[\"meta_info\"][\"finish_reason\"]\n\n        if (\n            finish_reason.get(\"type\") == \"abort\"\n            and finish_reason.get(\"status_code\") == HTTPStatus.BAD_REQUEST\n        ):\n            if not is_stream:\n                raise ValueError(finish_reason[\"message\"])\n            return out\n\n        if finish_reason.get(\"type\") == \"abort\" and finish_reason.get(\n            \"status_code\"\n        ) in (\n            HTTPStatus.SERVICE_UNAVAILABLE,\n            HTTPStatus.INTERNAL_SERVER_ERROR,\n        ):\n            # Delete the key to prevent resending abort request to the scheduler and\n            # to ensure aborted request state is cleaned up.\n            if state.obj.rid in self.rid_to_state:\n                del self.rid_to_state[state.obj.rid]\n\n            # Mark ongoing LoRA request as finished.\n            if self.enable_lora and state.obj.lora_path:\n                await self.lora_registry.release(state.obj.lora_id)\n            if not is_stream:\n                raise fastapi.HTTPException(","sourceCodeStart":1647,"sourceCodeEnd":1683,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/managers/tokenizer_manager.py#L1647-L1683","documentation":"Raised by _handle_abort_finish_reason when a non-streaming request finishes with finish_reason type 'abort' and status_code 400 (BAD_REQUEST): the server rejected the request and the stored message is re-raised client-side as a ValueError inside _wait_one_response.","triggerScenarios":"Non-streaming /generate call whose request is aborted by the scheduler/tokenizer with HTTP 400 — e.g. input validation failures, context-length overflow flagged as bad request — so finish_reason['message'] is surfaced by raising ValueError.","commonSituations":"Client sees a generic ValueError wrapping the server's abort message; common with over-length prompts, invalid sampling params, or other 400-class aborts on the non-stream path.","solutions":["Read the wrapped message — it contains the underlying abort reason from the server","Fix the root cause named in the message (prompt length, params, malformed input)","For richer error metadata, use the streaming path or check response finish_reason/status fields"],"exampleFix":"# before\nout = client.generate(prompt, sp)  # raises ValueError('...abort message...')\n# after\ntry:\n    out = client.generate(prompt, sp)\nexcept ValueError as e:\n    logger.error('server rejected request: %s', e); raise","handlingStrategy":"try-catch","validationCode":"if resp.get('finish_reason', {}).get('type') == 'abort':\n    raise for streamed path / inspect finish_reason['message'] before using output","typeGuard":null,"tryCatchPattern":"try:\n    out = await tokenizer_manager._wait_one_response(rid, request_types, stream)\nexcept ValueError as e:\n    # e.args[0] is the server's abort message; log and surface to caller\n    raise HTTPBadRequest(detail=str(e)) from e","preventionTips":["Always inspect finish_reason on responses","Wrap non-streaming generate calls and propagate the abort message verbatim"],"tags":["sglang","abort","bad-request","non-streaming"],"backgroundTag":"request-aborted-by-server","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}