Build1 distinct publisher2 min readUpdated
In one shop's database, every phone number saved with a country code lost its tail to a varchar(10) column, and nothing errored. Turning strict mode on mostly moves the loss.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
Nothing in the stack lies about this, which is why it survives review. MySQL treats the statement as complete, so affected_rows comes back 1, so a PDO connection in exception mode has nothing to throw, so the ORM reports a successful save, and an integration test asserting that the row exists is correct to pass [4]. Every layer honours its contract. None of those contracts says that the characters you sent are the characters that got stored.
The worked example drops two characters out of twelve [14], which is the awkward size for this class of bug: small enough to read as a formatting quirk, big enough to change what the value means.
The number worth computing during an audit is not how many rows sit at a column's limit, but what share of one input class does. In the case the author documents, the count at the limit was every row that had ever been saved with a country code [8], a 100 percent truncation rate for that input [17]. That is not an edge case leaking past validation. That is the normal write path for internationally formatted input, working as configured.
One trap while running the count: LENGTH() counts bytes and CHAR_LENGTH() counts characters, and VARCHAR(n) limits characters, so on multi-byte text a byte count will disagree with the limit the server actually enforces [9].
Strict mode does not narrow the gap between what the application sends and what the column accepts; it changes which side of the write reports the gap [11]. The second case in the source material is the one that should set the order of work. Strict mode was on and correct, the column was varchar(150), and the admin form carried neither a maxlength nor a server-side length check, so an editor who pasted a long headline got a blank error page and lost a story they believed they had saved [12]. The sql_mode setting decided where the loss landed. It did not remove it.
That puts the config change last, not first. Generate the limits out of information_schema and enforce them at the boundary, since a hand-copied constant drifts the first time somebody runs an ALTER [13]. Then change sql_mode, because in that order the user gets a validation message and in the other order they get an error page [16]. The audit and the flip are two different pieces of work, and only one of them can be done in an afternoon.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
A shop's WhatsApp button dialled a number three digits shorter than the one in the admin panel; the column was varchar(10), the number arrived with a country code, and MySQL chopped the value to fit and carried on. The column had been wrong for months and nothing in the stack raised an error.
Running SELECT @@GLOBAL.sql_mode, @@SESSION.sql_mode shows whether STRICT_TRANS_TABLES or STRICT_ALL_TABLES is set; if neither is present, then for every INSERT and UPDATE the server is in the business of making data fit rather than reporting that it does not fit.
Inserting '905551234567' into a VARCHAR(10) column produces Level: Warning, Code: 1265, 'Data truncated for column', and a stored value of 9055512345.
The truncation is a warning, not an error: the statement succeeded, affected_rows is 1, PDO in exception mode throws nothing because MySQL considers the statement completed, the ORM reports success, and an integration test asserting the row exists passes.
Truncated values cannot be recovered because the tail is gone, and unlike a crash there is no timestamp to correlate against: the row does not tell you when it happened or how many rows before it went the same way.
The same fit-it-and-continue mechanism applies well beyond strings.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Reproducible mechanics, anecdotal prevalence
The technical core is independently checkable by any reader: a named sql_mode check, a CREATE/INSERT/SHOW WARNINGS transcript with error code 1265 and the exact stored value, error 1406 for the strict-mode case, and an information_schema audit query with correct CHAR_LENGTH-vs-LENGTH reasoning. What is not evidenced is scope: both incidents are the author's unverifiable first-person accounts, there is no vendor documentation, dataset or third-party report in the cluster, and the article's charset section breaks off mid-sentence.
No adoption signal in cluster
The cluster contains no release, deployment, benchmark, pricing, licensing or usage-disclosure evidence. The story describes a database configuration behaviour and a remediation practice; nothing in the supplied source indicates how widely the audit or the boundary-validation pattern is used, and the single reported incident is not an adoption measurement. Rather than infer a figure from the author's anecdote, this dimension is left unmeasured.
Slightly understated relative to its own evidence
The framing is unusually self-limiting for the genre: it says plainly that truncated data is unrecoverable, that strict mode does not fix the mismatch but relocates it into 1406 errors and 500s, and that a wrong schema is the disease rather than truncation. The only stretch is generalising a single shop's 100 percent truncation rate for country-code numbers into a family of bugs, which the reproducible MySQL behaviour largely absorbs.
Low commercial incentive
The observable incentive structure is weak: an individual author posting on dev.to, no product, service, vendor, sponsor, pricing or licensing interest promoted anywhere in the body, and remediation advice that points to stock MySQL features and a few lines of hand-written PHP. Residual incentive is the usual practitioner-platform reward for a dramatic headline ('MySQL Will Quietly Eat Your Data'), which is reflected in framing rather than in the technical claims.
Mechanism solid, scope unconfirmed
High confidence in the behavioural claims — warning 1265 on non-strict writes, error 1406 under strict mode, character-vs-byte semantics of CHAR_LENGTH — because they are stated with executable specifics. Low confidence in scope and severity beyond this one estate: a single publisher, a single article, two self-reported incidents, no adoption evidence, and a body text that is cut off before the charset argument concludes.
build
Your Magento admin is slow because order state lives in fifteen tables, not because Varnish is off1 distinct publisher
build
Six MariaDB versions, one real difference: the only reason to leave 10.6 is the July 2026 clock1 distinct publisher
build
Slow Magento reindexes are a price index problem, and raw SQL makes it worse1 distinct publisher
build
Four indexes, none of them covering: the 78-second page and the one index that fixed it1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 23, 2026