Skip to content

Commit 184c34b

Browse files
zzstoatzzclaude
andcommitted
fix: prevent dictionary mutation during iteration in preprocess_schema
When processing schema definitions with block_type_slug where the definition's title differs from the dict key, the code would add a new key to the definitions dict while iterating over it, causing: RuntimeError: dictionary changed size during iteration This fix iterates over a snapshot of the dict values using list() to allow safe modification during iteration. Fixes #19935 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent ae8ed34 commit 184c34b

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

src/prefect/utilities/schema_tools/validation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ def preprocess_schema(
257257

258258
if "definitions" in schema: # Also process definitions for reused models
259259
definitions = cast(dict[str, Any], schema["definitions"])
260-
for definition in definitions.values():
260+
for definition in list(definitions.values()):
261261
if "properties" in definition:
262262
required_fields = definition.get("required", [])
263263
process_properties(

tests/utilities/schema_tools/test_validation.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,6 +1977,42 @@ class MyModel(BaseModel):
19771977
}
19781978

19791979

1980+
class TestPreprocessSchemaBlockTypes:
1981+
"""Regression tests for block type handling in preprocess_schema.
1982+
1983+
See: https://github.com/PrefectHQ/prefect/issues/19935
1984+
"""
1985+
1986+
def test_block_type_slug_with_mismatched_title_does_not_raise(self):
1987+
"""When a definition has block_type_slug and the dict key differs from
1988+
the title, preprocess_schema should not raise RuntimeError.
1989+
1990+
This bug occurred because the code modified schema["definitions"] while
1991+
iterating over it - adding a new key when title != dict key.
1992+
"""
1993+
schema = {
1994+
"properties": {
1995+
"my_block": {"$ref": "#/definitions/prefect__blocks__system__Secret"}
1996+
},
1997+
"definitions": {
1998+
# Key is the full module path, but title is just "Secret"
1999+
"prefect__blocks__system__Secret": {
2000+
"title": "Secret", # Different from the dict key!
2001+
"block_type_slug": "secret",
2002+
"type": "object",
2003+
"properties": {"value": {"type": "string"}},
2004+
}
2005+
},
2006+
}
2007+
2008+
# This should not raise RuntimeError: dictionary changed size during iteration
2009+
result = preprocess_schema(schema)
2010+
2011+
# The schema should be transformed to include oneOf for block reference
2012+
assert "Secret" in result["definitions"]
2013+
assert "oneOf" in result["definitions"]["Secret"]
2014+
2015+
19802016
class TestPreprocessSchemaPydanticV2Tuples:
19812017
# We should always be conforming to PydanticV2 and there should
19822018
# be no unintended changes here.

0 commit comments

Comments
 (0)