Skip to content

Supabase database errorSupabase: “null value in column violates not-null constraint” (23502)

“null value in column violates not-null constraint” is Postgres error 23502. A row was saved with no value in a required column, and the error names that column. In Supabase it is often a user_id the app never sends, or a sign-up trigger that writes a missing field.

Short answer

Find the column in the error, and the Failing row contains line that shows the row. If the app should fill it, send it in the insert. If the database can fill it, add a default, such as default auth.uid() for user_id or default now() for a timestamp. If the error comes from a trigger, fix the trigger. Make a column NOT NULL only after its old rows have values.

Rather not fix it yourself? App Fix Ticket starts with a fixed-price diagnosis, then a fixed price for the fix before any fix work.

Why the column is empty, and the fix

  1. 01

    The insert doesn’t send the column

    “If no default value is declared explicitly, the default value is the null value.” PostgreSQL docs, Default values

    A column left out of the insert gets its default. With no default, that is null, and a NOT NULL column refuses it.

  2. 02

    user_id should come from the session

    Let the database fill user_id from the signed-in user, so the client can’t forget it or send someone else’s. Keep an RLS policy that checks it. A default only applies when the column is left out: an explicit null still fails, and so does an insert from a signed-out client, because auth.uid() is null. In supabase-js bulk inserts, missing fields become null unless you pass defaultToNull: false.

    alter table public.todos
      alter column user_id set default auth.uid();
    
    -- the client can now insert without user_id
    -- supabase.from('todos').insert({ title: 'Buy milk' })
  3. 03

    A sign-up trigger writes a missing field

    A trigger on auth.users that copies raw_user_meta_data into a profile writes null when sign-up didn’t send that field. Sign-up then fails with “Database error saving new user”. Use coalesce with a fallback, or allow null in that column.

    insert into public.profiles (id, full_name)
    values (new.id, coalesce(new.raw_user_meta_data->>'full_name', ''));
  4. 04

    An update sets the column to null

    “A not-null constraint simply specifies that a column must not assume the null value.” PostgreSQL docs, Constraints (not-null)

    An update or upsert that sends the column as null, for example from an empty form field, fails the same way. Leave the field out of the update when it has no value.

  5. 05

    Making an old column required

    “SET NOT NULL may only be applied to a column provided none of the records in the table contain a NULL value for the column.” PostgreSQL docs, ALTER TABLE

    Adding NOT NULL to a column that already has empty rows fails. Fill them first, then add the constraint.

    update public.todos set status = 'open' where status is null;
    alter table public.todos alter column status set not null;

Checked against the vendor’s docs on : PostgreSQL docs: Constraints (not-null); PostgreSQL docs: Default values; PostgreSQL docs: ALTER TABLE.

Rather hand it over?

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

“Very responsive, attentive to fixing bugs, and completed the project as needed! Thank you!”
A buyer in the United States, July 2022. Shopify on Fiverr
All 127 Fiverr reviews

Related: Supabase violates check constraint · Supabase “Database error saving new user” · Supabase violates foreign key constraint · Supabase new row violates row-level security

Questions

More on this error

Should I just remove NOT NULL?

Only if the column can truly be empty. For a field like user_id, an empty value means a row no one owns, so a default is the better fix.

Does a default work with RLS?

Yes. The default fills user_id before the policy checks the row, so an insert policy such as with check (auth.uid() = user_id) passes.

Can you fix it for me?

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.

A different error?

Describe it and get a written quote

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; Simon replies by email, usually within one business day.