Skip to main content

MY.L5.SQL_MODE_NOT_STRICT — a truncated value the server called a success

  • Category: safety
  • Level: 5
  • Confidence: deterministic
  • Downtime class: none
  • Stability: stable
  • Suites: audit
  • Applies to: MySQL 8.4
  • Not transferable to MariaDB: this page describes MySQL 8.4 behavior. MariaDB answers the same driver and does not share these semantics, so SQLens refuses it outright rather than reasoning about it — see drivers/unsupported.

Without STRICT_TRANS_TABLES, an out-of-range number, an over-long string or an invalid date is truncated and the INSERT reports success with a warning nobody reads.

The application believes it stored what it sent. The shortened value is found later — by whoever notices the data is wrong. That is the most expensive shape a defect can take: a successful statement.

Flagged

SET GLOBAL sql_mode = 'NO_ZERO_DATE';

Preferred

SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

Why four rules and not one

Four independent guards live in the single sql_mode variable, and a project may legitimately accept one while wanting the others.

Under a single id, one ignore-list entry would silence all four — and whoever added it could not say afterwards which one they had accepted. Each flag therefore gets its own rule, its own id and its own consequence, because a shared "a flag is missing" message would tell a reader what is wrong without telling them why it matters.

What is read, and what is not

Only the server's value. Laravel sets sql_mode per connection from the connection's strict flag, so an application connection can be strict while the server hands something laxer to everything else that connects — a queue worker with different config, a migration run by hand, a reporting tool.

A flag is matched exactly, never as a substring: NO_ZERO_DATE is contained in NO_ZERO_IN_DATE, and a substring check would report a server carrying only the second as if it carried both.

An empty sql_mode is called out on its own. It is a legal value and a deliberate-looking one, and reporting it as "one flag missing" would understate a server running with every guard off at once.

A value the server withholds is reported as undetermined with a reason, never as a pass.

Sources