All rules Rule SR002 · DW
SurrealDB · beta
warning
DW · Deploy window
free in the CLI, --engine=surrealdb

Does changing a field type in SurrealDB convert existing records?

Field type changed in place

Warning: the statement succeeds, then writes fail, access changes, or the table is held up.

What happens

Observed on SurrealDB 3.0.2: a record stored with age = 'twelve' keeps that value after DEFINE FIELD OVERWRITE age ON person TYPE int, and its next write fails with "Couldn't coerce value for field `age`". INFO FOR TABLE shows the DEFAULT and ASSERT the old definition had are gone.

Why it is dangerous on a populated table

SurrealDB checks a schema change against new writes, not the records already stored, so an empty table hides it: on a populated one every old record is a write waiting to fail, and whole-table work runs for the length of the table in one transaction.

Fires on

DEFINE FIELD OVERWRITE age ON TABLE person TYPE int;

The safe pattern

Change the type in steps: add a new optional field with the new type, backfill it from the old one in batches, move readers and writers over, and remove the old field in a later migration.

DEFINE FIELD age_years ON TABLE person TYPE option<int>;
-- batched job: UPDATE person SET age_years = <int> age WHERE age_years IS NONE AND ...;
-- later migration: REMOVE FIELD age ON TABLE person;

Fixtures

The rule ships with these files and the test suite runs them on every change: the first set must fire, the second must stay silent.

Fires (2)

alter field type
ALTER FIELD age ON TABLE person TYPE int;
overwrite type
DEFINE FIELD OVERWRITE age ON TABLE person TYPE int;

Stays silent (3)

new field
DEFINE FIELD age_years ON TABLE person TYPE option<int>;
new table
DEFINE TABLE person SCHEMAFULL;
ALTER FIELD age ON TABLE person TYPE int;
overwrite comment only
DEFINE FIELD OVERWRITE age ON TABLE person TYPE any COMMENT 'years';

How to check locally

Catch this before it ships

SurrealDB support is in beta: this rule runs locally in the free CLI over .surql migrations, static only, and not in the hosted service yet. No install, nothing leaves your machine:

npx bolvrk check migration.surql --engine=surrealdb