huggingface/transformers · error · ValueError
You must provide only one of `prefix_to_add` and `prefix_to_
Error message
You must provide only one of `prefix_to_add` and `prefix_to_remove`
What it means
Raised by PrefixChange.__init__ (core_model_loading.py:1100). This transform either adds a key prefix or removes one — exactly one action per instance. The XOR check `(prefix_to_add is None) ^ (prefix_to_remove is not None)` raises when BOTH arguments are None (nothing to do, almost certainly a caller bug) or when BOTH are provided (ambiguous direction).
Source
Thrown at src/transformers/core_model_loading.py:1100
class PrefixChange(WeightRenaming):
"""
Special case of WeightRenaming, used to simplify adding/removing full parts of a weight name. The regexes
that are needed for such operations are complex, so this is a much easier API for such cases.
"""
__slots__ = (
"prefix_to_add",
"prefix_to_remove",
"model_prefix",
)
def __init__(
self, prefix_to_add: str | None = None, prefix_to_remove: str | None = None, model_prefix: str | None = None
):
if (prefix_to_add is None) ^ (prefix_to_remove is not None):
raise ValueError("You must provide only one of `prefix_to_add` and `prefix_to_remove`")
self.prefix_to_add = prefix_to_add
self.prefix_to_remove = prefix_to_remove
self.model_prefix = "" if model_prefix is None else model_prefix
prefix = rf"{self.model_prefix}\." if self.model_prefix != "" else ""
if prefix_to_add is not None:
super().__init__(
# We use a lookbehind to avoid adding the prefix if we detect that it's already present
source_patterns=rf"^{prefix}(?:(?!{prefix_to_add}\.))(.+)$",
target_patterns=rf"{prefix}{prefix_to_add}\.\1",
)
else:
super().__init__(source_patterns=rf"^{prefix}{prefix_to_remove}\.(.+)$", target_patterns=rf"{prefix}\1")
def reverse_transform(self) -> WeightTransform:
"""Reverse the current `WeightTransform` instance, to be able to save with the opposite weight transformations."""
# TODO: check this and relax when quantizer have `reverse_op`View on GitHub (pinned to a597f97485)
Solutions
- Pass exactly one of prefix_to_add or prefix_to_remove.
- Use keyword arguments to make the intent explicit.
- If your code computes prefixes conditionally, assert that exactly one is non-None before constructing.
Example fix
# before PrefixChange(prefix_to_add='visual', prefix_to_remove='visual') # raises # after PrefixChange(prefix_to_add='visual') # or PrefixChange(prefix_to_remove='visual')
Defensive patterns
Strategy: validation
Validate before calling
assert (prefix_to_add is None) != (prefix_to_remove is None), (
'provide exactly one of prefix_to_add / prefix_to_remove'
) Type guard
def is_exactly_one_set(*vals) -> bool:
return sum(v is not None for v in vals) == 1 Prevention
- Always call PrefixChange with a single keyword argument (prefix_to_add=... XOR prefix_to_remove=...).
- When prefixes come from config, assert exactly one is non-None before constructing.
- Remember model_prefix is optional and orthogonal — it never replaces the add/remove pair choice.
When it happens
Trigger: PrefixChange() with no arguments, or PrefixChange(prefix_to_add='visual', prefix_to_remove='visual'). Also triggered by code that passes both because it copies defaults.
Common situations: Programmatically building prefix transforms and passing the same variable to both parameters, or forgetting to pass either. Common in scripts that migrate key prefixes between checkpoint formats (e.g. adding/removing 'model.' or 'vision_tower.').
Related errors
- GroupWeightRename requires N:N length matching, but found le
- source keys={self.source_patterns}, target_patterns={self.ta
- WeightConverter requires at least one operation.
- Multiple different capturing groups found in target_patterns
- Source pattern '{pattern}' contains \\1 backreference, but n
AI-assisted analysis of huggingface/transformers@a597f97485 (2026-08-14).
Data as JSON: /api/errors/b8a1c3087f2bf402.
Report an issue: GitHub.