{"record":{"id":"2133f0899c85c62d","repo":"sqlalchemy/alembic","slug":"don-t-know-how-to-comma-format-r","errorCode":null,"errorMessage":"Don't know how to comma-format %r","messagePattern":"Don't know how to comma-format %r","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"alembic/util/messaging.py","lineNumber":120,"sourceCode":"            subsequent_indent=indent,\n        )\n        if len(lines) > 1:\n            for line in lines[0:-1]:\n                write_outstream(sys.stdout, line, \"\\n\")\n        write_outstream(sys.stdout, lines[-1], (\"\\n\" if newline else \"\"))\n    if flush:\n        sys.stdout.flush()\n\n\ndef format_as_comma(value: str | Iterable[str] | None) -> str:\n    if value is None:\n        return \"\"\n    elif isinstance(value, str):\n        return value\n    elif isinstance(value, Iterable):\n        return \", \".join(value)\n    else:\n        raise ValueError(\"Don't know how to comma-format %r\" % value)\n","sourceCodeStart":102,"sourceCodeEnd":121,"githubUrl":"https://github.com/sqlalchemy/alembic/blob/5551b5d35f985c99cb8f1af2b3c526b050e4c059/alembic/util/messaging.py#L102-L121","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nrev.branch_labels = 42  # should be a set/tuple\nutil.format_as_comma(rev.branch_labels)  # ValueError\n\n# after\nrev.branch_labels = {'label_42'}\nutil.format_as_comma(rev.branch_labels)","handlingStrategy":"type-guard","validationCode":"from collections.abc import Iterable\n\ndef can_format_as_comma(value):\n    return value is None or isinstance(value, str) or isinstance(value, Iterable)","typeGuard":"from collections.abc import Iterable\n\ndef is_comma_formattable(value) -> bool:\n    \"\"\"Type guard: True if format_as_comma can handle this value.\"\"\"\n    return value is None or isinstance(value, (str, Iterable))","tryCatchPattern":null,"preventionTips":["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."],"tags":["alembic","formatting","type-error","revision-metadata","valueerror"],"backgroundTag":null,"analyzedSha":"5551b5d35f985c99cb8f1af2b3c526b050e4c059","analyzedAt":"2026-08-11T01:38:46.612Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}