{"record":{"id":"1b7ec5f2c33d5524","repo":"python/cpython","slug":"must-be-str-not-s","errorCode":null,"errorMessage":"must be str, not %s","messagePattern":"must be str, not (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/_pydatetime.py","lineNumber":1124,"sourceCode":"        weekday = self.toordinal() % 7 or 7\n        return \"%s %s %2d 00:00:00 %04d\" % (\n            _DAYNAMES[weekday],\n            _MONTHNAMES[self._month],\n            self._day, self._year)\n\n    def strftime(self, format):\n        \"\"\"\n        Format using strftime().\n\n        Example: \"%d/%m/%Y, %H:%M:%S\"\n        For a list of supported format codes, see the documentation:\n            https://docs.python.org/3/library/datetime.html#format-codes\n        \"\"\"\n        return _wrap_strftime(self, format, self.timetuple())\n\n    def __format__(self, fmt):\n        if not isinstance(fmt, str):\n            raise TypeError(\"must be str, not %s\" % type(fmt).__name__)\n        if len(fmt) != 0:\n            return self.strftime(fmt)\n        return str(self)\n\n    def isoformat(self):\n        \"\"\"Return the date formatted according to ISO.\n\n        This is 'YYYY-MM-DD'.\n\n        References:\n        - https://www.w3.org/TR/NOTE-datetime\n        - https://www.cl.cam.ac.uk/~mgk25/iso-time.html\n        \"\"\"\n        return \"%04d-%02d-%02d\" % (self._year, self._month, self._day)\n\n    __str__ = isoformat\n\n    # Read-only field accessors","sourceCodeStart":1106,"sourceCodeEnd":1142,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pydatetime.py#L1106-L1142","documentation":"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').","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nfmt = b'%Y-%m-%d'\ns = format(d, fmt)\n\n// after\nfmt = '%Y-%m-%d'\ns = format(d, fmt)","handlingStrategy":"type-guard","validationCode":"if not isinstance(fmt, str):\n    fmt = fmt.decode('utf-8') if isinstance(fmt, (bytes, bytearray)) else str(d)\ns = format(d, fmt)","typeGuard":"def is_str_spec(fmt) -> bool:\n    return isinstance(fmt, str)","tryCatchPattern":"try:\n    s = format(d, fmt)\nexcept TypeError:\n    s = str(d)  # or re-raise after logging the spec type","preventionTips":["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"],"tags":["datetime","typeerror","formatting","bytes"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}