sgl-project/sglang · error · ValueError
only one of 'replacement', 'prepend', 'append' may be set, g
Error message
only one of 'replacement', 'prepend', 'append' may be set, got: {', '.join(active)} What it means
A patch/edit spec object validates that at most one of its three mutation modes — `replacement`, `prepend`, `append` — is non-empty. Setting two or more is contradictory (replace AND prepend what?) so _check_modes_mutually_exclusive raises ValueError at construction/validation time.
Source
Thrown at python/sglang/srt/debug_utils/source_patcher/types.py:38
Use ``prepend`` to keep the matched text and add lines before it.
Use ``append`` to keep the matched text and add lines after it.
Only one of ``replacement``, ``prepend``, and ``append`` may be set.
"""
match: str
replacement: str = ""
prepend: str = ""
append: str = ""
@model_validator(mode="after")
def _check_modes_mutually_exclusive(self) -> "EditSpec":
active: list[str] = [
name
for name in ("replacement", "prepend", "append")
if getattr(self, name).strip()
]
if len(active) > 1:
raise ValueError(
f"only one of 'replacement', 'prepend', 'append' may be set, "
f"got: {', '.join(active)}"
)
return self
class PatchSpec(_StrictBase):
target: str
edits: list[EditSpec]
preamble: str = ""
class PatchConfig(_StrictBase):
patches: list[PatchSpec]
class PatchState:
def __init__(View on GitHub (pinned to 0132848349)
Solutions
- Keep exactly one of `replacement`/`prepend`/`append` populated per edit and clear the others (set to "")
- If you need prepend AND replace, split into two sequential edits each with its own match anchor
- The error message lists the offending field names — remove all but the one you intend
Example fix
// before Edit(match=m, replacement="new body", prepend="# comment\n") // after Edit(match=m, replacement="# comment\nnew body")
Defensive patterns
Strategy: validation
Validate before calling
active = [n for n in ('replacement','prepend','append') if getattr(edit, n).strip()]\nif len(active) > 1:\n raise ValueError(f'configure only one mode, got {active}') Type guard
def is_valid_edit(e) -> bool:\n active = [n for n in ('replacement','prepend','append') if getattr(e, n).strip()]\n return len(active) == 1 Try / catch
try:\n edit.validate() # or construct inside try\nexcept ValueError as e:\n # e lists offending fields; blank out all but the intended one\n for n in ('replacement','prepend','append'):\n if n not in intended:\n setattr(edit, n, '') Prevention
- Construct edit specs with only one mode argument keyword
- When reusing spec objects, reset fields before assigning a new mode
- Assert exactly one active mode in unit tests for spec builders
When it happens
Trigger: Creating an edit spec with both `replacement` and `prepend` set (or any two of the three), including when one is set to a whitespace-only string that still passes `.strip()` truthiness checks in reverse — actually only non-blank strings count, so the trigger is two fields with non-blank content.
Common situations: Copy-pasting an existing edit spec and adding a new field without clearing the old one; refactoring code that used to allow combined semantics; programmatically filling fields from a dict that contains leftover keys.
Related errors
- v_cache must be provided
- q can only be None when only_qv=True
- q must be provided unless qv is provided with only_qv=True
- name must be provided
- batching config rule cannot set both model and model_contain
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/6c9b13d02f3e642e.
Report an issue: GitHub.