The Nil UUID
The Nil UUID is 128 zero bits: 00000000-0000-0000-0000-000000000000. RFC 9562 defines it as the identifier that names nothing, and it deliberately carries neither a version nor a variant.
Every codebase eventually needs a value that means "no identifier yet". The standard supplies one, and using it well is mostly about deciding where it may appear and where it must not.
00000000-0000-0000-0000-000000000000outuuid · NCS (0xxx) — reserved, backward compatibility · no version · nil, palindromeNil, and a palindrome as a bonus
ffffffff-ffff-ffff-ffff-ffffffffffffoutuuid · reserved for the future (111x) · no version · max, palindromeMax, its opposite number
On this page (8)
The definition#
All 128 bits are zero. Because the version and variant fields are part of those bits, the Nil UUID matches no version and no standard variant, which is precisely what makes it unmistakable. No generator can produce it by accident, and no strict RFC regex accepts it.
RFC 9562 § 5.9 · Nil UUIDThe Nil UUID
Every spelling of it#
| Spelling | Nil | Where it is expected |
|---|---|---|
| plain | 00000000-0000-0000-0000-000000000000 | The canonical form. What RFC 9562 writes and what every parser accepts. |
| hex | 00000000000000000000000000000000 | .NET format N. What a CHAR(32) column and most cache keys hold. |
| braces | {00000000-0000-0000-0000-000000000000} | .NET format B. The Windows registry and COM write this. |
| urn | urn:uuid:00000000-0000-0000-0000-000000000000 | A valid URN, for XML, RDF and anything that needs a URI. |
| upper case | 00000000-0000-0000-0000-000000000000 | Case is not significant; Windows tools write capitals. |
Nil or NULL#
| Nil UUID | NULL | |
|---|---|---|
| Fits a NOT NULL column | yes | no |
| Survives a protobuf field with no presence | yes | no |
| Distinguishes "unset" from "unknown" | no | yes, if you keep the discipline |
| Indexed like any other value | yes | depends on the engine |
| Joins accidentally to other Nil rows | **yes** — the trap | no, NULL never equals NULL |
That last row is the reason to be careful. Two unrelated rows both holding Nil in a foreign key will join to each other and to any Nil parent, silently. NULL refuses to join, which is usually what you actually wanted.
Where Nil earns its place#
- Wire formats without null: gRPC and protobuf scalar fields, where an absent value is indistinguishable from a zero one.
- A sentinel root in a self-referencing tree, so the root row needs no special case.
- The lower bound of a range scan over identifiers — Max is the matching upper bound.
- Test fixtures where an obviously fake identifier is clearer than a random one.
Validating it#
Because Nil fails a strict version-and-variant check, any parser that enforces RFC 9562 has to accept it as an explicit special case. Decide once, at the edge: either the field admits placeholders, in which case Nil is allowed by name, or it does not, in which case Nil is rejected like any other malformed value.
RFC 9562 § 4.1 · Variant FieldThe variant field, which Nil does not satisfy
Questions people actually ask#
What is 00000000-0000-0000-0000-000000000000?
The Nil UUID from RFC 9562 section 5.9: 128 zero bits, an identifier that names nothing.
Is the Nil UUID valid?
It is defined by the standard, but it has neither a version nor an RFC variant, so a strict validation pattern rejects it unless you allow it by name.
Should I use Nil instead of NULL?
Only where NULL is unavailable, such as a protobuf scalar. In SQL, remember that two Nil foreign keys will happily join to each other while two NULLs never do.
Related#
Browse the reference
Start here
Making and converting in bulk
Converting a UUID
Reading one
The versions, in order
In a database
ULID and the alternatives
Running the tool