sqlalchemy/alembic · error · ValueError
Don't know how to comma-format %r
Error message
Don't know how to comma-format %r
What it means
Raised as ValueError by format_as_comma when the value argument is not None, not a str, and not an Iterable (messaging.py:112-120). format_as_comma is a utility that converts revision lists, branch labels, and similar collections into comma-separated strings. Passing a non-iterable scalar (like an int) is a type contract violation.
Solutions
- Ensure the value passed to format_as_comma is a string, an iterable of strings, or None.
- If the error comes from internal Alembic code, inspect the Revision object's attributes (branch_labels, dependencies, nextrev) for type correctness.
- Wrap scalars in a list/tuple before passing: format_as_comma([my_value]) if a single value is intended.
- Check custom Script subclasses that override attributes returning revision collections.
Example fix
# before
rev.branch_labels = 42 # should be a set/tuple
util.format_as_comma(rev.branch_labels) # ValueError
# after
rev.branch_labels = {'label_42'}
util.format_as_comma(rev.branch_labels) Defensive patterns
Strategy: type-guard
Validate before calling
from collections.abc import Iterable
def can_format_as_comma(value):
return value is None or isinstance(value, str) or isinstance(value, Iterable) Type guard
from collections.abc import Iterable
def is_comma_formattable(value) -> bool:
"""Type guard: True if format_as_comma can handle this value."""
return value is None or isinstance(value, (str, Iterable)) Prevention
- Ensure Revision attributes (branch_labels, dependencies, nextrev) are always set/tuple/set types.
- Never assign scalar values to collection attributes on Revision objects.
- Validate custom Revision/Script subclasses return correct types for collection attributes.
When it happens
Trigger: Calling util.format_as_comma(value) where value is a non-iterable, non-string, non-None type like an int, bool, or float. Internally called from script/base.py and runtime/migration.py to format revision collections for display. Triggered when a Revision attribute that should be a collection/tuple is instead set to a scalar.
Common situations: A custom Script/Revision subclass that returns an integer or object instead of a tuple for nextrev, branch_labels, or dependencies. Corrupted revision metadata where a tuple field is overwritten with a scalar. Monkey-patching Revision internals incorrectly.
Related errors
- Can not set dispatch function for object
- no dispatch function for object
- String or text() construct expected
- A plugin named is already registered
- Can't change down_revision on a refresh operation.
AI-assisted analysis of sqlalchemy/alembic@5551b5d35f (2026-08-11).
Data as JSON: /api/errors/2133f0899c85c62d.
Report an issue: GitHub.
Appendix: source
Thrown at alembic/util/messaging.py:120
subsequent_indent=indent,
)
if len(lines) > 1:
for line in lines[0:-1]:
write_outstream(sys.stdout, line, "\n")
write_outstream(sys.stdout, lines[-1], ("\n" if newline else ""))
if flush:
sys.stdout.flush()
def format_as_comma(value: str | Iterable[str] | None) -> str:
if value is None:
return ""
elif isinstance(value, str):
return value
elif isinstance(value, Iterable):
return ", ".join(value)
else:
raise ValueError("Don't know how to comma-format %r" % value)
View on GitHub (pinned to 5551b5d35f)