python/cpython · error · TypeError
must be str, not %s
Error message
must be str, not %s
What it means
Raised by date.__format__ when the format specification passed to format(a_date, fmt) or an f-string is not a str instance. The datetime module only accepts string format specs; passing bytes or any other type is rejected immediately before strftime is called. The message names the actual type received (e.g. 'bytes', 'int').
Source
Thrown at Lib/_pydatetime.py:1124
weekday = self.toordinal() % 7 or 7
return "%s %s %2d 00:00:00 %04d" % (
_DAYNAMES[weekday],
_MONTHNAMES[self._month],
self._day, self._year)
def strftime(self, format):
"""
Format using strftime().
Example: "%d/%m/%Y, %H:%M:%S"
For a list of supported format codes, see the documentation:
https://docs.python.org/3/library/datetime.html#format-codes
"""
return _wrap_strftime(self, format, self.timetuple())
def __format__(self, fmt):
if not isinstance(fmt, str):
raise TypeError("must be str, not %s" % type(fmt).__name__)
if len(fmt) != 0:
return self.strftime(fmt)
return str(self)
def isoformat(self):
"""Return the date formatted according to ISO.
This is 'YYYY-MM-DD'.
References:
- https://www.w3.org/TR/NOTE-datetime
- https://www.cl.cam.ac.uk/~mgk25/iso-time.html
"""
return "%04d-%02d-%02d" % (self._year, self._month, self._day)
__str__ = isoformat
# Read-only field accessorsView on GitHub (pinned to bc6749cc3b)
Solutions
- Decode the format spec to str before formatting: fmt.decode('utf-8') if it is bytes
- Pass a literal str format spec, e.g. format(d, '%Y-%m-%d') or f"{d:%Y-%m-%d}"
- Default to str(d) when the spec variable may be None or non-string
Example fix
// before fmt = b'%Y-%m-%d' s = format(d, fmt) // after fmt = '%Y-%m-%d' s = format(d, fmt)
Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(fmt, str):
fmt = fmt.decode('utf-8') if isinstance(fmt, (bytes, bytearray)) else str(d)
s = format(d, fmt) Type guard
def is_str_spec(fmt) -> bool:
return isinstance(fmt, str) Try / catch
try:
s = format(d, fmt)
except TypeError:
s = str(d) # or re-raise after logging the spec type Prevention
- Keep format templates as str literals or decoded constants
- Decode bytes from files/env at the I/O boundary, not at format time
- Use f-string literal specs where possible so the type is guaranteed
When it happens
Trigger: format(date(2024,1,1), b'%Y-%m-%d'); f"{d:{fmt}}" where fmt is bytes (e.g. read from a file or config without decoding); format(some_date, None); calling format(date_obj, 42).
Common situations: Format strings loaded from binary files, network payloads, or environ/os.environb values that are bytes; passing a variable that was never decoded; programmatically building format specs from non-string data.
Related errors
- fromisoformat: argument must be str
- tzinfo.tzname() must return None or string, not {type(name).
- tzinfo.{name}() must return None or timedelta, not {type(off
- tzinfo argument must be None or of a tzinfo subclass, not {t
- unsupported type for timedelta {name} component: {type(value
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/1b7ec5f2c33d5524.
Report an issue: GitHub.