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

  1. Ensure the value passed to format_as_comma is a string, an iterable of strings, or None.
  2. If the error comes from internal Alembic code, inspect the Revision object's attributes (branch_labels, dependencies, nextrev) for type correctness.
  3. Wrap scalars in a list/tuple before passing: format_as_comma([my_value]) if a single value is intended.
  4. 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

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


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)