Skip to content

driver-sql (MySQL): nothing sees the 65535-byte row budget, so a table with many wide declared bounds fails CREATE with an error naming no field #11565

Description

@claude

Found while implementing #11431 (the string family honouring its declared maxLength). Filed unassigned. Not fixed there: the remedy needs a seam createColumn does not have.

What

MySQL InnoDB caps the sum of a row's declared byte widths at 65535, independently of the per-column varchar ceiling. createColumn decides one column at a time and cannot see that budget, so an object whose string-family fields declare enough total width simply fails CREATE TABLE.

Evidence

Measured on live MySQL 8.0.46 (utf8mb4, InnoDB, DYNAMIC row format):

 1 x varchar(16383) OK 4 x varchar(4096) ERROR 1118
2 x varchar(16383) ERROR 1118 32 x varchar(500) OK
15 x varchar(1024) OK 33 x varchar(500) ERROR 1118
16 x varchar(1024) ERROR 1118 64 x varchar(255) OK
65 x varchar(255) ERROR 1118
ERROR 1118 (42000): Row size too large. The maximum row size for the used table
type, not counting BLOBs, is 65535.

Postgres has no equivalent limit — it TOASTs; 40 x varchar(4096) creates cleanly. So this is MySQL-only.

Why it matters

The server's own error names no field and no declaration. It says "change some columns to TEXT or BLOBs" about a table the author described entirely in metadata, and nothing maps it back to the maxLength values that caused it. That is the same class of misleading diagnostic explainUnkeyableTextColumn was written for (#11374): a refusal an operator cannot act on without knowing the driver's internals.

It is reachable by ordinary authoring: sixteen fields declaring maxLength: 1024 is not an exotic object, and an AI-authoring a metadata app has no reason to suspect a cumulative limit exists.

Not currently triggered by this repo

Measured across every *.object.ts: the widest string-family bound declared anywhere is 2000, and no object carries more than six such fields. So no platform object is near the limit today — this is about authored apps.

Why it was not fixed in #11431

Two reasons, both structural rather than effort:

  1. createColumn is per-column by signature. The budget is a per-TABLE fact, known only at the call site that iterates obj.fields.
  2. Attaching a diagnostic means wrapping the shared knex.schema.createTable call inside initObjects in a try/catch — a hot region that sibling cards are working in.

Direction (for triage — not prescribing)

Either a pre-flight check at the call site that sums the declared widths before issuing DDL and refuses with a message naming the widest offenders, or an ER_TOO_BIG_ROWSIZE translator alongside explainUnkeyableTextColumn. The pre-flight is the better shape — it can name every contributing field, where the post-hoc translator only knows the table failed.


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions