Skip to content
SimpleTools24

Nil UUID and Max UUID: What They Are and When to Use Them

By SimpleTools24Published 3 min read

The nil UUID is the special UUID with all 128 bits set to zero: 00000000-0000-0000-0000-000000000000. The max UUID has all bits set to one: ffffffff-ffff-ffff-ffff-ffffffffffff. RFC 9562 defines both as special-case values outside the normal version and variant rules. The nil UUID commonly means "no value" or "not set", and .NET calls it Guid.Empty; the max UUID can serve as a sentinel, such as an upper bound in ranges.

What the Standard Says

RFC 9562, published in 2024, defines:

  • Nil UUID: all bits zero. Long recognised in earlier specifications too.
  • Max UUID: all bits one. Newly named in RFC 9562.

Neither follows the version and variant layout of normal UUIDs. A strict validator that checks for versions 1–8 and the standard variant will reject both unless it allows them explicitly.

How Languages Represent Them

Nil and max UUID in common languages
Language / platformNil UUIDMax UUID
.NETGuid.EmptyGuid.AllBitsSet (.NET 9+)
Python 3.14+uuid.NILuuid.MAX
Javanew UUID(0L, 0L)new UUID(-1L, -1L)
JavaScript (uuid package)NIL exportMAX export (recent versions)
PostgreSQL'00000000-0000-0000-0000-000000000000'::uuid'ffffffff-ffff-ffff-ffff-ffffffffffff'::uuid

Legitimate Uses

"No Value" Without NULL

Some systems use the nil UUID instead of NULL where a column can't be nullable, or where a struct type (like .NET's Guid) can't be null. It's a recognisable placeholder: "this reference hasn't been set".

Sentinels and Boundaries

The max UUID can mark an upper bound when paginating or partitioning by UUID ranges, and the nil UUID a lower bound.

Tests and Fixtures

Both are handy as obviously fake, deterministic values in tests.

When a Nil UUID Is a Bug

Unexpected nil UUIDs in production data usually point to a mistake:

  • Uninitialised fields. In C#, a Guid property defaults to Guid.Empty. If code forgets to assign Guid.NewGuid(), records get saved with the nil value. new Guid() also returns Guid.Empty, a frequent typo.
  • Failed parsing with a fallback. Some code returns the nil UUID when parsing fails, silently turning bad input into a "valid" ID.
  • Serialisation defaults. Missing JSON fields deserialised into non-nullable UUID types become nil.
  • Unique constraint collisions. If several records are saved with the nil UUID, a unique key will reject the second one, which is often how the bug is discovered.

Treat a nil UUID arriving from outside as invalid for most identifiers, and guard against saving it:

csharp
if (entity.Id == Guid.Empty) throw new InvalidOperationException("Id not set");
python
import uuid
if value == uuid.UUID(int=0):
    raise ValueError("nil UUID is not a valid identifier here")

Validation Policy

Decide explicitly:

  • Accept as "unset": only if your data model uses it that way.
  • Reject: for IDs that must point to real records, which is most of them.
  • Accept max UUID: almost never as a record ID; only as an internal boundary.

UUID regex patterns shows a strict pattern that excludes both, and why a UUID is invalid covers other input problems. If you're working in .NET, how to generate a GUID in C# explains the new Guid() trap in context.

Spotting Them in Your Data

When debugging, paste a list of IDs into the UUID validator. It checks up to 1,000 values, recognises nil and max UUIDs, and shows each valid value's version, variant and canonical form, so all-zero placeholders stand out quickly.

Nil UUID in APIs and JSON

APIs sometimes return the nil UUID where null would be clearer:

json
{ "orderId": "8b0c...", "parentOrderId": "00000000-0000-0000-0000-000000000000" }

Clients then have to know that the nil value means "none". If you design the API, prefer null or omitting the field. If you consume one, map the nil UUID to your language's null or empty value at the boundary, so the rest of your code doesn't need to know about the convention.

Databases

  • PostgreSQL stores the nil UUID like any other value; a NOT NULL column will happily accept it, which can hide missing data.
  • SQL Server uniqueidentifier columns behave the same way.
  • A CHECK constraint can block it where it should never appear:
sql
ALTER TABLE orders
  ADD CONSTRAINT orders_id_not_nil
  CHECK (id <> '00000000-0000-0000-0000-000000000000');

Frequently Asked Questions

Is the nil UUID a valid UUID?

Yes. It's a special value defined by the standard, though it doesn't have a version.

What is Guid.Empty?

.NET's name for the nil UUID, 00000000-0000-0000-0000-000000000000.

Should I store nil UUIDs or NULL?

Prefer NULL for "no value" where the database and language allow it. It's clearer and works naturally with constraints.

When was the max UUID introduced?

RFC 9562 (May 2024) formally defined it.

Summary

Nil (all zeros) and max (all f's) are special UUIDs outside the version rules. Use them deliberately as placeholders or bounds, and treat an unexpected nil UUID as a bug to fix at its source.

Sources