# Supabase: “invalid input syntax for type uuid” (22P02)

> Postgres error 22P02 means a value sent to a uuid column isn’t a UUID: often "undefined", an empty string or a number. Check the value before the query.

Canonical: https://app369.com/fix/supabase-invalid-input-syntax-for-type-uuid/
Last updated: 2026-11-09

Invalid input syntax for type uuid is Postgres error 22P02: the app sent a value to a uuid column that isn’t a UUID. In Supabase apps the value is often the text "undefined", an empty string, a number or an id from another auth provider.

**Short answer**

Log the value you pass to .eq() or the insert. If it is "undefined" or empty, wait for the user or route param before running the query. If it is a number or a slug, query the column that holds it. If ids come from another auth provider, store them in a text column.

Rather not fix it yourself? [**App Fix Ticket**](https://app369.com/fixed-price/flutter-firebase-bug-fix/) starts with a fixed-price diagnosis, then a fixed price for the fix before any fix work.

## **Where the bad value comes from, and the fix**

1. 01 ### **The id is undefined when the query runs**
  > “22P02 invalid_text_representation” [**PostgreSQL docs, PostgreSQL error codes**](https://www.postgresql.org/docs/current/errcodes-appendix.html) A query that runs before the session or the route param loads can send the text "undefined" or "null" as the id. Postgres can’t read that as a UUID. Skip the query until the value exists. Check ids read from the URL or local storage too: a stored "undefined" string is the same bug, and so is one bad entry in an .in() list.```
// inside an async function
const { data: { user } } = await supabase.auth.getUser();
if (!user) return; // no session yet: don't query

const { data, error } = await supabase
  .from('profiles')
  .select('*')
  .eq('id', user.id)
  .single();
if (error?.code === '22P02') console.error('bad uuid', user.id);
```
2. 02 ### **A form sends an empty string** An empty select or hidden field sends "" for a foreign key. Send null instead, and make the column nullable if the link is optional.```
const row = { title, category_id: categoryId || null };
```
3. 03 ### **A number or slug goes into a uuid column**
  > “A UUID is written as a sequence of lower-case hexadecimal digits, in several groups separated by hyphens” [**PostgreSQL docs, UUID type**](https://www.postgresql.org/docs/current/datatype-uuid.html) A route like /posts/12 or /posts/my-first-post passes 12 or a slug, but the id column is uuid. Filter on the column that holds that value, such as slug, or link with the UUID.
4. 04 ### **User ids come from another auth provider** Firebase, Clerk and other providers use ids that aren’t UUIDs, such as user_2abc. A user_id column of type uuid rejects them. Store those ids in a text column, or map each user to a Supabase auth user. After the change, rewrite RLS policies that use auth.uid() so they compare text with text, or they fail with operator does not exist: uuid = text.```
-- Back up first. Foreign keys to auth.users(id), views and policies that use
-- this column must be dropped and rebuilt. With Clerk or Firebase ids,
-- compare against (auth.jwt() ->> 'sub') in your policies.
alter table public.orders alter column user_id type text using user_id::text;
```
5. 05 ### **The format is fine, the characters aren’t**
  > “PostgreSQL also accepts the following alternative forms for input: use of upper-case digits, the standard format surrounded by braces, omitting some or all hyphens” [**PostgreSQL docs, UUID type**](https://www.postgresql.org/docs/current/datatype-uuid.html) Postgres accepts upper case, braces and missing hyphens, so formatting is rarely the cause. A stray space, quote marks or a cut-off id is. Trim the value and check it has 32 hex digits.

Checked against the vendor’s docs on November 9, 2026: [PostgreSQL docs: UUID type](https://www.postgresql.org/docs/current/datatype-uuid.html); [PostgreSQL docs: Error codes](https://www.postgresql.org/docs/current/errcodes-appendix.html).

## **Rather hand it over?**

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

- [from $450**App Fix Ticket**One reproducible bug in an existing mobile or web app, diagnosed and fixed.**See scope and start**](https://app369.com/fixed-price/flutter-firebase-bug-fix/)
- [from $450**AI-Built App Rescue**A Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.****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.**See scope and start**](https://app369.com/fixed-price/ai-app-rescue/)

[**All 127 Fiverr reviews**](https://app369.com/reviews/)

Related: [**Supabase operator does not exist: uuid = text**](https://app369.com/fix/supabase-operator-does-not-exist-uuid-text/) · [**Supabase select returns an empty array**](https://app369.com/fix/supabase-select-returns-empty-array/) · [**Supabase PGRST116 single row**](https://app369.com/fix/supabase-pgrst116-single-row/) · [**Supabase value too long for type character varying**](https://app369.com/fix/supabase-value-too-long-for-type-character-varying/)

Questions

## **More on this error**

<details>

<summary>**Why does it work for me and fail for others? **+</summary>

The query often runs before the user or route param loads. On a fast connection the value is ready in time; on a slow one the query sends "undefined". Guard the query until the value exists.

</details>

<details>

<summary>**Should I change the id column to text? **+</summary>

Only if it stores ids that aren’t UUIDs, such as ids from another auth provider. For Supabase auth users, keep uuid and fix the value you send.

</details>

<details>

<summary>**Can you fix it for me? **+</summary>

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.

</details>

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.

[**Describe your problem **→](https://app369.com/contact/) [**All fixes**](https://app369.com/fix/)