Skip to content

fix: handle non-string input in Replace validator gracefully#540

Open
gaoflow wants to merge 1 commit into
alecthomas:masterfrom
gaoflow:fix/replace-non-string-typeerror
Open

fix: handle non-string input in Replace validator gracefully#540
gaoflow wants to merge 1 commit into
alecthomas:masterfrom
gaoflow:fix/replace-non-string-typeerror

Conversation

@gaoflow

@gaoflow gaoflow commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

The Replace validator calls re.Pattern.sub() directly on the input value. When passed a non-string type (int, None, list, etc.), this raises an unhandled TypeError instead of the expected Invalid exception.

This matches the behavior of the Match validator, which already catches TypeError and raises a proper Invalid error with a descriptive message.

Before (crashes):

>>> from voluptuous.validators import Replace
>>> Replace('hello', 'goodbye')(42)
TypeError: expected string or bytes-like object, got 'int'

After:

>>> from voluptuous.validators import Replace
>>> Replace('hello', 'goodbye')(42)
voluptuous.error.MatchInvalid: expected string or buffer

Changes:

  • Replace._call_ now catches TypeError and raises MatchInvalid
  • Added test_replace_non_string_input covering int, None, list, and custom message cases

Replace.__call__ passed non-string values straight to re.Pattern.sub(),
which raises an unhandled TypeError. Wrap it and raise MatchInvalid
(honouring a custom msg), matching how Match reports the same case.
@gaoflow
gaoflow force-pushed the fix/replace-non-string-typeerror branch from 7ade908 to 4c75e63 Compare July 15, 2026 08:16
@gaoflow

gaoflow commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto master and dropped the unrelated quote-style churn from the diff — it's now just the Replace fix and its test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant