PostgreSQL · error reference
asyncpg: a sized iterable container expected (got type 'str')
invalid input for query argument $23: 'a,b' (a sized iterable container expected (got type 'str'))
asyncpg rejected a string bound to an array column. Nearly always a MySQL SET, or a comma-joined list that was never converted to a Python list.
What the database is telling you
The target column is an array type, so asyncpg expects a Python sequence and will not split a string for you. Postgres would accept the literal '{a,b}' over the text protocol; asyncpg's binary protocol will not guess — safer behaviour, confusing message.
Why it shows up in a migration
MySQL's SET type has no Postgres equivalent, so converters commonly map it to text[]. The DDL half of that is easy to get right and the value half is easy to forget: MySQL hands you the comma-joined string 'a,b', and unless something splits it the bind fails on every row with more than zero values. Because it fails per row rather than per batch, the usual symptom is a handful of quarantined rows and a row-count mismatch at the end — not an obvious crash.
Common causes
- A MySQL SET or ENUM-list column mapped to a Postgres array without converting the value.
- A comma-joined string built in application code and bound to an array column.
- A JSON array arriving as text rather than parsed.
- Engine detection missing an alias, so array conversion never ran — CockroachDB and YugabyteDB are the usual casualties.
How to fix it
- 1
Split the value before binding. An empty SET is an empty list, not a list holding one empty string.
# Python value = [] if not raw else raw.split(",") - 2
Or keep the column as text on the target if nothing queries it as an array.
ALTER TABLE items ALTER COLUMN tags TYPE text USING array_to_string(tags, ',');
- 3
Check the parameter index the error names ($23) against your column list — it identifies the column precisely.
What DBShifts does about it
The transformer converts SET and ENUM-list values to lists for array-typed targets, and resolves the target through the wire-compatible aliases first — so CockroachDB and YugabyteDB get the same conversion as Postgres. Before that fix, MySQL-to-CockroachDB quarantined four rows in five on any table with a SET column while still reporting rows transferred.
Value transformer
Migrating between engines?
DBShifts converts the schema, moves the data, and then proves the two sides match with a type-aware checksum per table — not just a row count. Errors like this one are handled on the way, and the ones that cannot be handled are reported rather than logged and forgotten.
Related errors
CockroachDB
CockroachDB: at or near "restart" syntax error on TRUNCATE
TRUNCATE ... RESTART IDENTITY CASCADE is valid Postgres and a syntax error on CockroachDB. The difference, and what to use instead.
CockroachDB
CockroachDB: unknown function pg_total_relation_size()
CockroachDB speaks the Postgres wire protocol but does not implement every pg_catalog function. Why tools that introspect Postgres fail on the size query specifically.