# invalid byte sequence for encoding UTF8: 0x00

> Postgres text can't hold the NUL character (0x00) or bytes that aren't valid UTF-8. Where the error comes from in imports and API inserts, and how to clean the data.

Source: https://supahost.app/kb/invalid-byte-sequence-utf8 · Updated 2026-11-11

## What you see

When importing a CSV, restoring a dump, or inserting from your app:

```
ERROR:  invalid byte sequence for encoding "UTF8": 0x00
CONTEXT:  COPY messages, line 1842
```

Sending JSON with a NUL character into a `jsonb` or `text` column through the Data API gives a close relative:

```
ERROR:  unsupported Unicode escape sequence
DETAIL:  \u0000 cannot be converted to text.
```

Both have SQLSTATE `22021` or `22P05`. A different byte in the message, such as `0xe9 0x20`, means the file isn't UTF-8 at all (often Latin-1 or Windows-1252).

## Why it happens

Project databases use the UTF-8 encoding (check with `show server_encoding;`), and Postgres `text`, `varchar` and `jsonb` values can't contain the NUL character. Other databases and languages allow it, so it sneaks in from:

- data scraped from PDFs or binary files,
- exports from SQLite or MySQL,
- strings from C libraries or badly decoded uploads,
- JSON payloads where a client wrote `"\u0000"`.

The value is rejected while Postgres converts the input, before any trigger runs. A trigger can't clean it up for you; the fix has to happen before the data reaches the database.

## How to fix it

**Strip NUL characters in your app before writing:**

```ts
const clean = (s: string) => s.replaceAll('\u0000', '')

await supabase.from('messages').insert({
  channel_id: channelId,
  body: clean(rawBody),
})
```

For nested objects, run the same function over every string value before sending.

**Clean a CSV or SQL file before importing:**

```bash
# remove NUL bytes
tr -d '\000' < messages.csv > messages-clean.csv

# convert a Latin-1 file to UTF-8
iconv -f LATIN1 -t UTF-8 export.csv > export-utf8.csv
```

Then import the cleaned file. In psql, `\copy messages from 'messages-clean.csv' with (format csv, header true)`.

**If the data really is binary**, store it in a `bytea` column, or better, as a file in Storage with only its path in the table.

## On SupaHost

- For large imports, see [Importing data](/docs/database/import-data). On Business you can run `\copy` through the SSH tunnel; on other plans use Studio's CSV import or insert in batches through the Data API.

## Related

- [Importing data (CSV, SQL dumps)](/docs/database/import-data)
- [Move an app from SQLite to Postgres](/kb/migrate-from-sqlite)
- [Migrate from MySQL](/kb/migrate-from-mysql)
