Skip to content

Commit 417668f

Browse files
committed
fix: reject ambiguous legacy dict-key names in load_state
Distinct dict keys such as "0" and 0 shared the single pre-#1302 name dict_a['0'], so the legacy fallback applied one saved state to both parameters. Raise a KeyError when the fallback name is ambiguous.
1 parent ba3bd6f commit 417668f

2 files changed

Lines changed: 25 additions & 0 deletions

File tree

‎dspy/primitives/base_module.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,13 @@ def _apply(module):
183183
if name in state:
184184
param_state = state[name]
185185
elif legacy_name in state:
186+
if legacy_names.count(legacy_name) > 1:
187+
raise KeyError(
188+
f"'{name}': the pre-fix name '{legacy_name}' is ambiguous (it was shared by several "
189+
'dict keys, e.g. "0" and 0, before '
190+
"https://github.com/stanfordnlp/dspy/issues/1302 was fixed), so the saved state cannot "
191+
"be mapped to a single parameter. Re-save the state with the current DSPy version."
192+
)
186193
param_state = state[legacy_name]
187194
else:
188195
raise KeyError(

‎tests/primitives/test_module.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,24 @@ def __init__(self):
222222
prog.load_state(legacy_state) # must not raise
223223

224224

225+
def test_load_state_rejects_ambiguous_pre_fix_dict_key_names():
226+
"""
227+
Distinct keys "0" and 0 shared the single legacy name "dict_a['0']", so a legacy state cannot say which
228+
parameter it belongs to. load_state() must reject it rather than apply one state to both parameters.
229+
"""
230+
231+
class Prog(Module):
232+
def __init__(self):
233+
super().__init__()
234+
self.dict_a = {"0": dspy.Predict("question -> answer"), 0: dspy.Predict("question -> answer")}
235+
236+
prog = Prog()
237+
legacy_state = {"dict_a['0']": prog.dict_a["0"].dump_state()}
238+
239+
with pytest.raises(KeyError, match="ambiguous"):
240+
prog.load_state(legacy_state)
241+
242+
225243
def test_load_state_raises_clear_error_when_name_missing_in_both_formats():
226244
"""
227245
A parameter missing under BOTH its current name and its pre-#1302 legacy name is a genuine

0 commit comments

Comments
 (0)