Title: [Bug] Uppercase `--log-level` (e.g. `WARN`) hangs the HTTP server: unnormalized value forwarded to uvicorn raises `KeyError` before the socket binds
### Checklist
- [x] I searched related issues but found no solution.
- [x] The bug persists in the latest version.
- [x] Issues without environment info and a minimal reproducible demo are hard to resolve and may receive no feedback.
- [x] If this is not a bug report but a general question, please start a discussion at https://github.com/sgl-project/sglang/discussions. Otherwise, it will be closed.
- [x] Please use English. Otherwise, it will be closed.
### Describe the bug
When `--log-level` (or `--log-level-http`) is given an uppercase or aliased value such as `WARN`, the HTTP server never comes up. SGLang forwards the string verbatim to uvicorn, and uvicorn raises `KeyError` while building its logging config — **before the listening socket binds**. The result is a silent hang: the scheduler/engine core initialize and sit idle, the port never starts listening, `/health_generate` is unreachable, and no clear error is surfaced.
The core inconsistency: SGLang's *own* stdlib logger accepts `WARN` (it does `getattr(logging, level.upper())` at [server_args.py L7044](https://github.com/sgl-project/sglang/blob/main/python/sglang/srt/server_args.py#L7044)), but SGLang forwards the same value unnormalized to uvicorn, which rejects it. A value SGLang treats as valid in one place crashes the HTTP server in another.
Root cause (current `main`):
1. `log_level` / `log_level_http` are declared with no `choices` and are never normalized — [server_args.py L1052-L1056](https://github.com/sgl-project/sglang/blob/main/python/sglang/srt/server_args.py#L1052-L1056); `ServerArgs.__post_init__` ([L2622](https://github.com/sgl-project/sglang/blob/main/python/sglang/srt/server_args.py#L2622)) never touches the level, so any string is accepted verbatim.
2. The value is forwarded verbatim to uvicorn as `log_level=server_args.log_level_http or server_args.log_level` — single-tokenizer path [http_server.py L2410-L2415](https://github.com/sgl-project/sglang/blob/main/python/sglang/srt/entrypoints/http_server.py#L2410-L2415), multi-tokenizer path [L2456-L2461](https://github.com/sgl-project/sglang/blob/main/python/sglang/srt/entrypoints/http_server.py#L2456-L2461); the same expression feeds the granian paths at [L2364](https://github.com/sgl-project/sglang/blob/main/python/sglang/srt/entrypoints/http_server.py#L2364) / [L2378](https://github.com/sgl-project/sglang/blob/main/python/sglang/srt/entrypoints/http_server.py#L2378).
3. uvicorn's `LOG_LEVELS` is keyed by lowercase names only — `critical / error / warning / info / debug / trace` — with **no `warn` key** ([uvicorn config.py L44-L51](https://github.com/encode/uvicorn/blob/master/uvicorn/config.py#L44-L51)); `Config.configure_logging()` does `LOG_LEVELS[self.log_level.lower()]`, so `WARN` (→ `warn`) raises `KeyError`. SGLang must normalize the value itself.
Expected: `--log-level WARN` either works (mapped to `warning`, consistent with SGLang's own logger) or fails immediately with a clear, actionable error. Actual: the HTTP server silently never binds.
### Reproduction
The bug is entirely in the value that reaches uvicorn, so it reproduces without loading a model. In a `sglang 0.5.12.post1` + `uvicorn 0.49.0` environment:
```python
import uvicorn
from sglang.srt.server_args import ServerArgs
sa = ServerArgs(model_path="dummy", log_level="WARN")
resolved = sa.log_level_http or sa.log_level # exactly what http_server.py passes
print(repr(resolved)) # -> 'WARN' (not normalized)
uvicorn.Config(app="x:y", log_level=resolved).configure_logging()
# -> KeyError('warn') (raised before any socket is created)
```
Run live, this prints `'WARN'` then raises `KeyError('warn')`; the same call with `log_level="warning"` succeeds.
End-user form (hangs instead of erroring):
```bash
python -m sglang.launch_server --model-path <any-model> --log-level WARN
# in another shell:
curl -sS http://127.0.0.1:30000/health_generate # hangs / connection refused
```
### Environment
`python3 -m sglang.check_env` (versions; the topology section is omitted because I reproduced this on a GPU-less process, which is sufficient since the bug is model- and device-independent):
```
Python: 3.12.3
SGLang: 0.5.12.post1
PyTorch: 2.11.0+cu130
CUDA (torch.version.cuda): 13.0
uvicorn: 0.49.0
flashinfer_python: 0.6.11.post1
transformers: 5.6.0
triton: 3.6.0
granian: 2.7.8
OS: Linux
```
Also confirmed present on current `main` by the permalinks above. uvicorn: reproduces on 0.49.0; the same KeyError occurs on 0.30.x–0.35.x (no `.lower()`) and on uvicorn master (has `.lower()` but still no `warn` key).
0 条评论