Quick answer: This TypeError means Python passed a non-empty format specification to an object whose __format__ method does not support it. Inspect the value’s type, convert deliberately to the intended type, or implement a documented __format__ contract for a custom class.

The error TypeError: non-empty format string passed to object.__format__ means Python received a format specification for an object that does not know how to handle it. The empty format spec works for almost every object because it behaves like a basic string conversion. A non-empty spec such as >20, .2f, or 08d requires the object’s type to implement matching formatting behavior.
You can run into this with plain objects, bytes, None, or a custom class that does not define a useful __format__() method. The fix is to format the right type, convert the value before formatting, handle missing values, or implement __format__() on the custom class. The official Python object.__format__ documentation explains the fallback behavior.
This is different from a syntax problem in the format string. The format string can be valid while the target object still rejects the requested format. For another TypeError caused by using the wrong operation on an object, see the method object is not subscriptable guide.
When debugging, inspect both sides of the formatting operation. The left side is the value being formatted, and the right side is the spec inside the braces. A quick type(value) check often reveals that the code is formatting bytes, None, or a wrapper object instead of the plain string or number you expected.
Reproduce The Error
A plain object has the base implementation of __format__(). That implementation accepts an empty format spec, but it rejects non-empty specs because it has no type-specific formatting rules.
item = object()
try:
print(f"{item:>20}")
except TypeError as exc:
print(exc)
The same idea applies when formatting calls format(item, ">20"). Python routes the request to type(item).__format__. If that method does not support the spec, Python raises a TypeError instead of guessing how the object should be aligned, rounded, padded, or converted.
Convert The Value Before Formatting
If your goal is display output, convert the object to a string before applying string formatting. In f-strings, the !s conversion calls str() first and then applies the format spec to the resulting text.
data = b"Hi"
print(f"{str(data):>20}")
print(f"{data!s:>20}")
This is useful for logs, labels, debug messages, and simple reports. It preserves the display representation of the object. If you need the actual text inside a bytes object, decode it instead of using the bytes representation.
Decode Bytes Before Text Formatting
Bytes are not normal text strings. If the bytes contain encoded text, decode them to str and then format the decoded text. This is clearer than formatting the bytes representation.
payload = b"Python"
text = payload.decode("utf-8")
print(f"{text:<12}")
print(f"{text.upper():^12}")
Only decode bytes when you know the encoding. UTF-8 is common, but files, network responses, and older systems may use a different encoding. The important step is that formatting is applied after you have the correct Python type.
If the bytes are binary data rather than encoded text, do not decode them just to satisfy formatting. Convert them to a safe display form such as a length, a hex preview, or a plain repr() string depending on what the output needs to communicate.
Handle None Before Numeric Formatting
None cannot be rounded with a numeric spec such as .2f. If a function can return None, check for it before formatting. This is common in reports, dashboards, and template code.
score = None
if score is None:
display = "n/a"
else:
display = f"{score:.2f}"
print(display)
Do not hide this case by converting everything to a string automatically if the missing value is important. A clear fallback such as "n/a", "missing", or an empty string makes the output intentional.
Implement __format__ For Custom Classes
When a custom class should support format specs, define __format__(). Inside that method, delegate to a value that already knows how to format itself. The format specification mini-language lists the standard spec options.
class Price:
def __init__(self, amount):
self.amount = amount
def __format__(self, spec):
return format(self.amount, spec or ".2f")
price = Price(19.5)
print(f"{price:.2f}")
This approach is better than formatting the object’s default representation when the object has a meaningful numeric, date, or text value. Keep the method small and predictable so callers can use normal Python formatting syntax.
Check Template Values Before Formatting
Template systems such as Jinja can surface this error when a template tries to apply a numeric format to a missing or unsupported object. The Jinja template documentation covers template expressions, but the underlying fix is still Python-side data cleanup.
def display_score(score):
if score is None:
return "n/a"
return f"{score:.1f}"
print(display_score(91.25))
print(display_score(None))
Prepare values before passing them to a template whenever possible. Templates should display data, not guess how to recover from unexpected object types. If a value can be absent, convert it to a display-safe fallback before rendering.
To fix TypeError: non-empty format string passed to object.__format__, first identify the value being formatted and the format spec being applied. Then choose the right repair: convert to string for display, decode bytes for text, guard None, use a numeric type for numeric specs, or implement __format__() for custom objects.
Read The Formatting Expression
In an f-string or format call, the text after a colon is passed to the value’s __format__ method. Record the exact value, type, conversion flag, and specification before changing the expression.
Convert Deliberately
If the value represents a number, date, decimal, or string, convert it to that type before formatting. Avoid stringifying everything blindly because that can hide invalid data and remove numeric formatting behavior.
Use Conversion Flags Carefully
The !s, !r, and !a conversions change the value before the format specification is applied. They can be useful for diagnostics, but the output contract should say whether a representation or a user-facing string is required.
Implement Custom __format__ Only When Needed
A domain object can implement __format__ for a small documented set of specifications and delegate unsupported cases to a clear error. Keep formatting separate from mutation or network work.
Check None And Unexpected Types
Values arriving from parsing, dictionaries, optional fields, or mocks may not have the type the happy path assumes. Validate at the boundary and produce a useful error before formatting.
Test Empty And Non-empty Specs
Test the default empty specification, every supported non-empty specification, invalid text, conversion flags, subclass behavior, and values from real input. Assert both output and exception type.
Use the official Python format documentation and the data model description of __format__. Related Python Pool references include tests and dictionary values.
For related formatting work, compare Python string handling, formatting tests, and value lookup before changing a format specification.
Frequently Asked Questions
What causes this non-empty format string TypeError?
The value is often a plain object or a custom class whose __format__ method does not support the requested non-empty specification.
How do I fix the error for an object?
Inspect the value’s type, convert it to the intended string, number, date, or other supported type, then apply a format specification that type accepts.
Why does an f-string trigger the error?
An f-string passes the text after the colon to the value’s __format__ method, so an unsupported specification raises the same underlying error.
Can I implement __format__ myself?
Yes, a custom class can define __format__ for documented specifications, but tests should cover empty and supported non-empty formats and reject invalid ones clearly.