From 1f5a614db6556167e03e2c709ac131a45b20de62 Mon Sep 17 00:00:00 2001 From: CjhHa1 Date: Tue, 25 Aug 2026 17:01:30 +0800 Subject: [PATCH] fix(sglang): surface dropped rollout arguments Warn when SGLang ignores unknown ServerArgs keys, with an opt-in strict failure mode, so recipe typos and version skew no longer fail silently. Document and annotate the intended Qwen3 colocate, async, and LoRA rollout presets. --- .../ar/qwen3_5_grpo_9b_base_dapo_sglang.yaml | 3 ++ .../ar/qwen3_5_grpo_9b_geo3k_mc_sglang.yaml | 1 + ...3_5_moe_grpo_35b_a3b_base_dapo_sglang.yaml | 2 ++ ...n3_5_moe_grpo_35b_a3b_geo3k_mc_sglang.yaml | 3 ++ .../qwen3_cppo_30b_a3b_base_dapo_sglang.yaml | 3 ++ ...a3b_base_dapo_sglang_full_weight_sync.yaml | 6 ++-- ...n3_cppo_30b_a3b_base_dapo_sglang_lora.yaml | 6 ++-- .../ar/qwen3_dppo_4b_base_dapo_sglang.yaml | 1 + .../ar/qwen3_drgrpo_4b_base_dapo_sglang.yaml | 1 + .../ar/qwen3_drpo_4b_base_dapo_sglang.yaml | 1 + .../qwen3_drpo_4b_base_dapo_sglang_async.yaml | 5 +-- .../ar/qwen3_drpo_4b_veomni_sp_sglang.yaml | 1 + .../ar/qwen3_grpo_4b_base_dapo_sglang.yaml | 1 + .../qwen3_grpo_4b_base_dapo_sglang_async.yaml | 5 +-- .../ar/qwen3_grpo_4b_veomni_sp_sglang.yaml | 1 + ...wen3_grpo_vanilla_4b_base_dapo_sglang.yaml | 1 + ...en3_moe_grpo_30b_a3b_veomni_ep_sglang.yaml | 2 ++ .../ar/qwen3_ppo_4b_base_dapo_sglang.yaml | 9 +++++ unirl/rollout/README.md | 32 +++++++++++++++++ unirl/rollout/engine/README.md | 6 ++++ unirl/rollout/engine/sglang/backends/base.py | 34 ++++++++++++++++++- 21 files changed, 115 insertions(+), 9 deletions(-) diff --git a/examples/ar/qwen3_5_grpo_9b_base_dapo_sglang.yaml b/examples/ar/qwen3_5_grpo_9b_base_dapo_sglang.yaml index 18d99b6b4..ccc7afe15 100644 --- a/examples/ar/qwen3_5_grpo_9b_base_dapo_sglang.yaml +++ b/examples/ar/qwen3_5_grpo_9b_base_dapo_sglang.yaml @@ -97,6 +97,9 @@ rollout: chat_template_kwargs: enable_thinking: true engine_kwargs: + # Colocate, but a larger KV/graph budget than the 4B full-FT preset + # (0.5 / cuda_graph_max_bs 128 vs 0.3 / 16). Retune if the FSDP all-gather OOMs. + # See unirl/rollout/README.md (SGLang AR knobs). mem_fraction_static: 0.5 skip_server_warmup: true attention_backend: triton diff --git a/examples/ar/qwen3_5_grpo_9b_geo3k_mc_sglang.yaml b/examples/ar/qwen3_5_grpo_9b_geo3k_mc_sglang.yaml index 084f9e665..8c229ef96 100644 --- a/examples/ar/qwen3_5_grpo_9b_geo3k_mc_sglang.yaml +++ b/examples/ar/qwen3_5_grpo_9b_geo3k_mc_sglang.yaml @@ -103,6 +103,7 @@ rollout: chat_template_kwargs: enable_thinking: false engine_kwargs: + # Colocate full-FT preset — see unirl/rollout/README.md (SGLang AR knobs). mem_fraction_static: 0.3 skip_server_warmup: true attention_backend: triton diff --git a/examples/ar/qwen3_5_moe_grpo_35b_a3b_base_dapo_sglang.yaml b/examples/ar/qwen3_5_moe_grpo_35b_a3b_base_dapo_sglang.yaml index db98302a9..67bf1aa88 100644 --- a/examples/ar/qwen3_5_moe_grpo_35b_a3b_base_dapo_sglang.yaml +++ b/examples/ar/qwen3_5_moe_grpo_35b_a3b_base_dapo_sglang.yaml @@ -106,6 +106,8 @@ rollout: chat_template_kwargs: enable_thinking: true engine_kwargs: + # Colocate MoE: tighter KV than the 4B dense preset (0.15 vs 0.3) and + # cuda_graph_max_bs=64. See unirl/rollout/README.md (SGLang AR knobs). mem_fraction_static: 0.15 attention_backend: triton disable_cuda_graph: false diff --git a/examples/ar/qwen3_5_moe_grpo_35b_a3b_geo3k_mc_sglang.yaml b/examples/ar/qwen3_5_moe_grpo_35b_a3b_geo3k_mc_sglang.yaml index 60299a055..ad12504f1 100644 --- a/examples/ar/qwen3_5_moe_grpo_35b_a3b_geo3k_mc_sglang.yaml +++ b/examples/ar/qwen3_5_moe_grpo_35b_a3b_geo3k_mc_sglang.yaml @@ -104,6 +104,9 @@ rollout: chat_template_kwargs: enable_thinking: false engine_kwargs: + # Colocate MoE + geo3k: cuda graph OFF and mem_fraction_static 0.15 + # (4B dense preset is 0.3 + cuda graph ON @ bs 16). + # See unirl/rollout/README.md (SGLang AR knobs). mem_fraction_static: 0.15 disable_cuda_graph: true enable_lora: false diff --git a/examples/ar/qwen3_cppo_30b_a3b_base_dapo_sglang.yaml b/examples/ar/qwen3_cppo_30b_a3b_base_dapo_sglang.yaml index f8150e1b2..4431720bb 100644 --- a/examples/ar/qwen3_cppo_30b_a3b_base_dapo_sglang.yaml +++ b/examples/ar/qwen3_cppo_30b_a3b_base_dapo_sglang.yaml @@ -113,6 +113,9 @@ rollout: chat_template_kwargs: enable_thinking: true engine_kwargs: + # Colocate full-FT preset (same KV/graph knobs as the 4B dense recipes; + # tp_size=8 is the MoE fit, not an engine_kwargs change). + # See unirl/rollout/README.md (SGLang AR knobs). mem_fraction_static: 0.3 skip_server_warmup: true attention_backend: triton diff --git a/examples/ar/qwen3_cppo_30b_a3b_base_dapo_sglang_full_weight_sync.yaml b/examples/ar/qwen3_cppo_30b_a3b_base_dapo_sglang_full_weight_sync.yaml index 3c0f0d732..8af67262f 100644 --- a/examples/ar/qwen3_cppo_30b_a3b_base_dapo_sglang_full_weight_sync.yaml +++ b/examples/ar/qwen3_cppo_30b_a3b_base_dapo_sglang_full_weight_sync.yaml @@ -113,8 +113,10 @@ rollout: chat_template_kwargs: enable_thinking: true engine_kwargs: - # Leaves room for FSDP offload/onload and staged SGLang wake on this - # 8-GPU 30B MoE recipe; retune when changing the model or TP layout. + # Colocate 30B MoE: tighter than the 4B dense preset (0.15 / cuda_graph_max_bs + # 64 vs 0.3 / 16) to leave room for FSDP offload/onload and staged SGLang + # wake. Retune when changing the model or TP layout. + # See unirl/rollout/README.md (SGLang AR knobs). mem_fraction_static: 0.15 attention_backend: triton disable_cuda_graph: false diff --git a/examples/ar/qwen3_cppo_30b_a3b_base_dapo_sglang_lora.yaml b/examples/ar/qwen3_cppo_30b_a3b_base_dapo_sglang_lora.yaml index a3c887403..00c94d821 100644 --- a/examples/ar/qwen3_cppo_30b_a3b_base_dapo_sglang_lora.yaml +++ b/examples/ar/qwen3_cppo_30b_a3b_base_dapo_sglang_lora.yaml @@ -124,8 +124,10 @@ rollout: chat_template_kwargs: enable_thinking: true engine_kwargs: - # Value used for the reported LoRA run; retune when changing the model, - # the TP layout, or the FSDP offload settings above. + # LoRA exception to the colocate full-FT preset (enable_lora: true + pool + # knobs; LocalLoraWeightSync). Value used for the reported LoRA run; retune + # when changing the model, the TP layout, or the FSDP offload settings. + # See unirl/rollout/README.md (SGLang AR knobs). mem_fraction_static: 0.5 attention_backend: triton disable_cuda_graph: false diff --git a/examples/ar/qwen3_dppo_4b_base_dapo_sglang.yaml b/examples/ar/qwen3_dppo_4b_base_dapo_sglang.yaml index 876820e40..126604af1 100644 --- a/examples/ar/qwen3_dppo_4b_base_dapo_sglang.yaml +++ b/examples/ar/qwen3_dppo_4b_base_dapo_sglang.yaml @@ -132,6 +132,7 @@ rollout: chat_template_kwargs: enable_thinking: true engine_kwargs: + # Colocate full-FT preset — see unirl/rollout/README.md (SGLang AR knobs). # FULL fine-tuning: lower the SRT KV reservation to give FSDP headroom for # the per-rollout full-weight all-gather. No LoRA pool — full dense weights # pushed via TensorWeightSync. CUDA graph ON for decode speed, but capped at diff --git a/examples/ar/qwen3_drgrpo_4b_base_dapo_sglang.yaml b/examples/ar/qwen3_drgrpo_4b_base_dapo_sglang.yaml index ed748cd94..7e756d3be 100644 --- a/examples/ar/qwen3_drgrpo_4b_base_dapo_sglang.yaml +++ b/examples/ar/qwen3_drgrpo_4b_base_dapo_sglang.yaml @@ -124,6 +124,7 @@ rollout: chat_template_kwargs: enable_thinking: true engine_kwargs: + # Colocate full-FT preset — see unirl/rollout/README.md (SGLang AR knobs). # FULL fine-tuning: lower the SRT KV reservation to give FSDP headroom for # the per-rollout full-weight all-gather. No LoRA pool — full dense weights # pushed via TensorWeightSync. CUDA graph ON for decode speed, but capped at diff --git a/examples/ar/qwen3_drpo_4b_base_dapo_sglang.yaml b/examples/ar/qwen3_drpo_4b_base_dapo_sglang.yaml index e54a21e6d..0e4593e8e 100644 --- a/examples/ar/qwen3_drpo_4b_base_dapo_sglang.yaml +++ b/examples/ar/qwen3_drpo_4b_base_dapo_sglang.yaml @@ -140,6 +140,7 @@ rollout: # FSDP trainer. Without it, rollout logprobs drift from replay and # SGLang 0.5.12.post1 also tries to JIT an incompatible activation kernel. rl_on_policy_target: fsdp + # Colocate full-FT preset — see unirl/rollout/README.md (SGLang AR knobs). # FULL fine-tuning: lower the SRT KV reservation to give FSDP headroom for # the per-rollout full-weight all-gather. No LoRA pool — full dense weights # pushed via TensorWeightSync. CUDA graph ON for decode speed, but capped at diff --git a/examples/ar/qwen3_drpo_4b_base_dapo_sglang_async.yaml b/examples/ar/qwen3_drpo_4b_base_dapo_sglang_async.yaml index bfdd3c5e2..a7f11f5f3 100644 --- a/examples/ar/qwen3_drpo_4b_base_dapo_sglang_async.yaml +++ b/examples/ar/qwen3_drpo_4b_base_dapo_sglang_async.yaml @@ -100,8 +100,9 @@ rollout: enable_thinking: true engine_kwargs: # Disaggregated: the engine owns the GPU (no colocated FSDP shard), so it - # can reserve more KV than the colocate recipe's 0.3. Leave headroom for - # the NCCL weight-receive buffers during the broadcast. + # can reserve more KV than the colocate full-FT preset's 0.3. Leave + # headroom for the NCCL weight-receive buffers during the broadcast. + # Other knobs match the colocate preset — see unirl/rollout/README.md. mem_fraction_static: 0.8 skip_server_warmup: true attention_backend: triton diff --git a/examples/ar/qwen3_drpo_4b_veomni_sp_sglang.yaml b/examples/ar/qwen3_drpo_4b_veomni_sp_sglang.yaml index f09207e61..989c371ee 100644 --- a/examples/ar/qwen3_drpo_4b_veomni_sp_sglang.yaml +++ b/examples/ar/qwen3_drpo_4b_veomni_sp_sglang.yaml @@ -134,6 +134,7 @@ rollout: chat_template_kwargs: enable_thinking: true engine_kwargs: + # Colocate full-FT preset — see unirl/rollout/README.md (SGLang AR knobs). # FULL fine-tuning: lower the SRT KV reservation to give FSDP headroom for # the per-rollout full-weight all-gather. No LoRA pool — full dense weights # pushed via TensorWeightSync. CUDA graph ON for decode speed, but capped at diff --git a/examples/ar/qwen3_grpo_4b_base_dapo_sglang.yaml b/examples/ar/qwen3_grpo_4b_base_dapo_sglang.yaml index 0fc316f2b..10d51d5fa 100644 --- a/examples/ar/qwen3_grpo_4b_base_dapo_sglang.yaml +++ b/examples/ar/qwen3_grpo_4b_base_dapo_sglang.yaml @@ -131,6 +131,7 @@ rollout: chat_template_kwargs: enable_thinking: true engine_kwargs: + # Colocate full-FT preset — see unirl/rollout/README.md (SGLang AR knobs). # FULL fine-tuning: lower the SRT KV reservation to give FSDP headroom for # the per-rollout full-weight all-gather. No LoRA pool — full dense weights # pushed via TensorWeightSync. CUDA graph ON for decode speed, but capped at diff --git a/examples/ar/qwen3_grpo_4b_base_dapo_sglang_async.yaml b/examples/ar/qwen3_grpo_4b_base_dapo_sglang_async.yaml index 7efef3189..cfc65f114 100644 --- a/examples/ar/qwen3_grpo_4b_base_dapo_sglang_async.yaml +++ b/examples/ar/qwen3_grpo_4b_base_dapo_sglang_async.yaml @@ -103,8 +103,9 @@ rollout: enable_thinking: true engine_kwargs: # Disaggregated: the engine owns the GPU (no colocated FSDP shard), so it - # can reserve more KV than the colocate recipe's 0.3. Leave headroom for - # the NCCL weight-receive buffers during the broadcast. + # can reserve more KV than the colocate full-FT preset's 0.3. Leave + # headroom for the NCCL weight-receive buffers during the broadcast. + # Other knobs match the colocate preset — see unirl/rollout/README.md. mem_fraction_static: 0.8 skip_server_warmup: true attention_backend: triton diff --git a/examples/ar/qwen3_grpo_4b_veomni_sp_sglang.yaml b/examples/ar/qwen3_grpo_4b_veomni_sp_sglang.yaml index 1d4fb976f..ce2b43491 100644 --- a/examples/ar/qwen3_grpo_4b_veomni_sp_sglang.yaml +++ b/examples/ar/qwen3_grpo_4b_veomni_sp_sglang.yaml @@ -135,6 +135,7 @@ rollout: chat_template_kwargs: enable_thinking: true engine_kwargs: + # Colocate full-FT preset — see unirl/rollout/README.md (SGLang AR knobs). # FULL fine-tuning: lower the SRT KV reservation to give FSDP headroom for # the per-rollout full-weight all-gather. No LoRA pool — full dense weights # pushed via TensorWeightSync. CUDA graph ON for decode speed, but capped at diff --git a/examples/ar/qwen3_grpo_vanilla_4b_base_dapo_sglang.yaml b/examples/ar/qwen3_grpo_vanilla_4b_base_dapo_sglang.yaml index 3893c88e4..5d857504b 100644 --- a/examples/ar/qwen3_grpo_vanilla_4b_base_dapo_sglang.yaml +++ b/examples/ar/qwen3_grpo_vanilla_4b_base_dapo_sglang.yaml @@ -133,6 +133,7 @@ rollout: chat_template_kwargs: enable_thinking: true engine_kwargs: + # Colocate full-FT preset — see unirl/rollout/README.md (SGLang AR knobs). # FULL fine-tuning: lower the SRT KV reservation to give FSDP headroom for # the per-rollout full-weight all-gather. No LoRA pool — full dense weights # pushed via TensorWeightSync. CUDA graph ON for decode speed, but capped at diff --git a/examples/ar/qwen3_moe_grpo_30b_a3b_veomni_ep_sglang.yaml b/examples/ar/qwen3_moe_grpo_30b_a3b_veomni_ep_sglang.yaml index d1eca15f9..2291a812c 100644 --- a/examples/ar/qwen3_moe_grpo_30b_a3b_veomni_ep_sglang.yaml +++ b/examples/ar/qwen3_moe_grpo_30b_a3b_veomni_ep_sglang.yaml @@ -119,6 +119,8 @@ rollout: chat_template_kwargs: enable_thinking: true engine_kwargs: + # Colocate MoE at tp_size=1: slightly more KV than the 4B dense preset + # (0.4 vs 0.3); other knobs match. See unirl/rollout/README.md (SGLang AR knobs). mem_fraction_static: 0.4 skip_server_warmup: true attention_backend: triton diff --git a/examples/ar/qwen3_ppo_4b_base_dapo_sglang.yaml b/examples/ar/qwen3_ppo_4b_base_dapo_sglang.yaml index 59989aa2d..e5b4fbe0b 100644 --- a/examples/ar/qwen3_ppo_4b_base_dapo_sglang.yaml +++ b/examples/ar/qwen3_ppo_4b_base_dapo_sglang.yaml @@ -86,7 +86,16 @@ rollout: chat_template_kwargs: enable_thinking: true engine_kwargs: + # SGLang's FSDP on-policy mode is part of the rollout/replay contract, + # not merely a performance switch. It selects deterministic PyTorch + # sampling/log-softmax and native activations/layernorms that match the + # FSDP trainer. Without it, rollout logprobs drift from replay and + # SGLang 0.5.12.post1 also tries to JIT an incompatible activation kernel. rl_on_policy_target: fsdp + # Colocate full-FT preset (unirl/rollout/README.md): lower the SRT KV + # reservation so FSDP can all-gather full dense weights. enable_lora must + # stay false for TensorWeightSync. CUDA graph ON, cuda_graph_max_bs=16 + # (SGLang default 256 would balloon server memory + compete with the push). mem_fraction_static: 0.3 skip_server_warmup: true attention_backend: triton diff --git a/unirl/rollout/README.md b/unirl/rollout/README.md index 726087287..4a266bc90 100644 --- a/unirl/rollout/README.md +++ b/unirl/rollout/README.md @@ -111,6 +111,38 @@ change surface: `pipelines//pipeline.py`; if the AR/DiT worker needs new behavior, add a `worker/` extension or `patches/compat_.py`. +## SGLang AR knobs + +Qwen3 AR recipes (`examples/ar/qwen3_*_sglang*.yaml`) share one **colocate +full-FT** `engine_kwargs` preset. Async/separate and larger-model recipes keep +the same keys and change the memory numbers. Typed `SGLangEngineConfig` fields +overlay `engine_kwargs`; reserved ports always win. Keys that are not live +SGLang `ServerArgs` fields warn at boot (or raise if +`UNIRL_SGLANG_STRICT_SERVER_ARGS=1`) — see [`engine/README.md`](engine/README.md). + +**Colocate full-FT preset** (FSDP train shard time-shares the GPU; TensorWeightSync): + +| Knob | Preset | Why | +|---|---|---| +| `mem_fraction_static` | `0.3` | Lower SRT KV reservation so FSDP can all-gather full dense weights. `server_intent()` defaults to `0.88` if omitted — too high for colocate. | +| `enable_lora` | `false` | TensorWeightSync pushes full dense weights; a LoRA pool would be the wrong receive path. | +| `cuda_graph_max_bs` | `16` | CUDA graph stays on (`disable_cuda_graph: false`); SGLang's default `256` captures buffers that fight the weight push. | +| `skip_server_warmup` | `true` | Skip SRT warmup on every colocated boot/wake. | +| `attention_backend` | `triton` | Matches the in-tree 4B full-FT recipes. | + +**Async / separate** (`*_sglang_async.yaml`): the engine owns the GPU (no colocated +FSDP shard). Raise `mem_fraction_static` to `0.8` and leave the other preset keys +as-is; keep headroom for NCCL weight-receive buffers. Sync is `NCCLWeightSync`. + +**LoRA colocate** (`*_sglang_lora.yaml`): `enable_lora: true` plus the SGLang LoRA +pool knobs. This is the exception to the full-FT `enable_lora: false` receive path +(`LocalLoraWeightSync` instead of TensorWeightSync). Memory numbers are recipe-specific. + +**Reserved ports:** `SGLangPorts.reserve()` binds HTTP `port` and `nccl_port` on +the engine's node. Server port is capped at 35535 because SGLang derives +`grpc_port = port + 30000`. Do not set `port` / `nccl_port` in `engine_kwargs` — +the reserved sockets overwrite them. + ## Gotchas - **Never recompute σ inside an engine** — the generated Part's pinned sigmas are diff --git a/unirl/rollout/engine/README.md b/unirl/rollout/engine/README.md index 53115e5ae..c55080eed 100644 --- a/unirl/rollout/engine/README.md +++ b/unirl/rollout/engine/README.md @@ -61,6 +61,12 @@ handler in `../../distributed/weight_sync`. - **An engine that will serve as an agentic inner must make `generate` safe for concurrent callers** — the agentic coordinator drives one trajectory per drain thread. +- **Unknown SGLang `engine_kwargs` are dropped at boot.** HTTP/native backends + filter intent against live `ServerArgs`. Typos used to fail silently; they now + warn, or raise if `UNIRL_SGLANG_STRICT_SERVER_ARGS=1`. UniRL-only keys + (`concurrency`, `advertise_host`, `health_timeout_s`) are expected drops. + Recipe-facing colocate/async knobs live in [`../README.md`](../README.md) + (SGLang AR knobs). - **One SGLang `MultiprocessingSerializer` LoRA payload is TP1-only.** Stock upstream serializes with `ForkingPickler`, whose `resource_sharer` file descriptors are one-shot: broadcasting the same payload to TP>1 scheduler diff --git a/unirl/rollout/engine/sglang/backends/base.py b/unirl/rollout/engine/sglang/backends/base.py index 95b42957f..900d8b136 100644 --- a/unirl/rollout/engine/sglang/backends/base.py +++ b/unirl/rollout/engine/sglang/backends/base.py @@ -4,6 +4,8 @@ import base64 import io +import logging +import os import pickle from typing import ( Any, @@ -15,7 +17,18 @@ runtime_checkable, ) +logger = logging.getLogger(__name__) + _REQUIRED_SERVER_ARGS_METADATA_KEY = "_unirl_required_server_args" +_STRICT_SERVER_ARGS_ENV = "UNIRL_SGLANG_STRICT_SERVER_ARGS" +_UNIRL_ONLY_INTENT_KEYS = frozenset( + { + _REQUIRED_SERVER_ARGS_METADATA_KEY, + "advertise_host", + "concurrency", + "health_timeout_s", + } +) def _serialize_lora_tensors( @@ -32,13 +45,22 @@ def _serialize_lora_tensors( return base64.b64encode(buf.getvalue()).decode("utf-8") +def _strict_dropped_server_args() -> bool: + return os.environ.get(_STRICT_SERVER_ARGS_ENV, "").strip().lower() in {"1", "true", "yes", "on"} + + +def _unknown_server_arg_keys(server_intent: Dict[str, Any], allowed: set[str]) -> List[str]: + """Intent keys that are neither live ``ServerArgs`` fields nor UniRL-only.""" + return sorted(key for key in server_intent if key not in allowed and key not in _UNIRL_ONLY_INTENT_KEYS) + + def _filter_server_args_or_raise( server_intent: Dict[str, Any], *, allowed: set[str], backend_name: str, ) -> Dict[str, Any]: - """Filter ``server_intent`` against real SGLang ``ServerArgs`` fields.""" + """Filter intent against live ServerArgs; unknown keys warn or raise — see ../../README.md.""" raw_required = server_intent.get(_REQUIRED_SERVER_ARGS_METADATA_KEY, ()) if isinstance(raw_required, str): required = [raw_required] @@ -51,6 +73,16 @@ def _filter_server_args_or_raise( "Upgrade SGLang to a build that supports these fields, or remove the explicit UniRL " "rollout config that depends on them." ) + dropped = _unknown_server_arg_keys(server_intent, allowed) + if dropped: + message = ( + f"SGLang {backend_name} backend dropping unknown ServerArgs keys: {dropped}. " + "They are not fields on the installed SGLang ServerArgs (typo or version skew). " + f"Set {_STRICT_SERVER_ARGS_ENV}=1 to fail closed." + ) + if _strict_dropped_server_args(): + raise RuntimeError(message) + logger.warning(message) return {k: v for k, v in server_intent.items() if k != _REQUIRED_SERVER_ARGS_METADATA_KEY and k in allowed}