python/cpython · error · TypeError
invalid errors: %r
Error message
invalid errors: %r
What it means
Raised by io.open() when the errors argument is supplied and is neither None nor a str. errors names the error handler for text decoding/encoding ('strict', 'replace', 'ignore', 'backslashreplace', ...); the validator rejects any non-string value with this TypeError before the stream is created.
Source
Thrown at Lib/_pyio.py:205
a BufferedRandom.
It is also possible to use a string or bytearray as a file for both
reading and writing. For strings StringIO can be used like a file
opened in a text mode, and for bytes a BytesIO can be used like a file
opened in a binary mode.
"""
if not isinstance(file, int):
file = os.fspath(file)
if not isinstance(file, (str, bytes, int)):
raise TypeError("invalid file: %r" % file)
if not isinstance(mode, str):
raise TypeError("invalid mode: %r" % mode)
if not isinstance(buffering, int):
raise TypeError("invalid buffering: %r" % buffering)
if encoding is not None and not isinstance(encoding, str):
raise TypeError("invalid encoding: %r" % encoding)
if errors is not None and not isinstance(errors, str):
raise TypeError("invalid errors: %r" % errors)
modes = set(mode)
if modes - set("axrwb+t") or len(mode) > len(modes):
raise ValueError("invalid mode: %r" % mode)
creating = "x" in modes
reading = "r" in modes
writing = "w" in modes
appending = "a" in modes
updating = "+" in modes
text = "t" in modes
binary = "b" in modes
if text and binary:
raise ValueError("can't have text and binary mode at once")
if creating + reading + writing + appending > 1:
raise ValueError("can't have read/write/append mode at once")
if not (creating or reading or writing or appending):
raise ValueError("must have exactly one of read/write/append mode")
if binary and encoding is not None:
raise ValueError("binary mode doesn't take an encoding argument")View on GitHub (pinned to bc6749cc3b)
Solutions
- Pass one of the documented handler names as a str ('strict', 'ignore', 'replace', 'backslashreplace', 'surrogateescape', 'xmlcharrefreplace', 'namereplace') or None.
- If the value is an enum/constant object, pass its string value (e.g. member.value).
- Fix conditional expressions: errors='strict' if strict_mode else 'replace'.
Example fix
// before
open('f', encoding='utf-8', errors=ErrorHandlers.IGNORE) # enum object -> TypeError
// after
open('f', encoding='utf-8', errors='ignore') # str handler name Defensive patterns
Strategy: type-guard
Validate before calling
HANDLERS = {'strict','ignore','replace','backslashreplace','surrogateescape','xmlcharrefreplace','namereplace'}
if errors is not None:
assert isinstance(errors, str) and errors in HANDLERS, f'bad errors handler: {errors!r}'
open(path, errors=errors) Type guard
def valid_errors_handler(e) -> bool:
return e is None or (isinstance(e, str) and e in {
'strict','ignore','replace','backslashreplace',
'surrogateescape','xmlcharrefreplace','namereplace'}) Prevention
- Store error-handler names as strings in settings, not enum objects or booleans.
- If using an enum, pass member.value to open().
- Write conditionals as 'strict' if strict else 'replace', not strict and 'strict'.
When it happens
Trigger: open('f', 'r', errors=None) is fine, but errors=0, errors=['ignore'], or a typo'd constant (e.g. errors=IGNORE vs the string 'ignore') raises it. Also errors=sys.stderr (confusing the stream with its error attribute) or errors='ignore '.strip miswired.
Common situations: Passing module constants instead of their string names; wiring the argument from a settings object whose attribute is an enum or bool instead of str; conditional expressions like errors=strict_mode and 'strict' that evaluate to False.
Related errors
- invalid encoding: %r
- invalid file: %r
- invalid mode: %r
- invalid buffering: %r
- can't have text and binary mode at once
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/fc3411a4014f02e6.
Report an issue: GitHub.