Most graphs have an identifier property somewhere: id, uuid, userId. For years that identifier has been a NUMBER, or a STRING that happens to look like a UUID, and nothing stopped a different kind of string, or an integer, from sneaking in next to it.
Neo4j 2026.08 added a native UUID type. Graph types can enforce it, so the database can now insist that an identifier really is a UUID.
This guide shows how to declare a UUID property in a graph type, generate values for it, and what happens when a write breaks the rule. If you've not used GRAPH TYPEs before, start with Graph types kept our AI honest or the Graph Type Schema Enforcement course.
Before you start
You need a Neo4j instance running 2026.08 or later. We ran everything below on 2026.10.1.
Declare the property
Add UUID to an element type the same way you would add STRING or INTEGER. This example gives every Thing node a mandatory id:
ALTER CURRENT GRAPH TYPE SET {
(:Thing => {
id :: UUID NOT NULL,
name :: STRING
})
}Check what the database stored:
SHOW CURRENT GRAPH TYPE(:`Thing` => {`id` :: UUID NOT NULL, `name` :: STRING})Thing is the identifying label, so the rule applies to every node that carries it. id is mandatory and must be a UUID. name is optional, but if present it must be a STRING.
Generate values with uuid()
The uuid() function returns a new UUID value, so it satisfies the type without any conversion:
CREATE (:Thing {id: uuid()})The write succeeds. The same function is the easiest way to give every new node an identifier at creation time.
The 2026.08 release also added constructor forms and helper functions such as uuid.mostSignificantBits() and uuid.leastSignificantBits(). The Cypher Manual's UUID section covers them in full.
See what a bad write looks like
Now try to store a plain string that merely looks like an identifier:
CREATE (:Thing {id: 'abc'})The database rejects it:
22N78: data exception - property type verification failed. NODE (1) with label 'Thing' must have the property `id` with value type UUID.The error names the label, the property and the expected type, which makes it easy to trace back to the offending query. Nothing is written, so there is no clean-up afterwards.
This is the point of the exercise. A string that looks like an identifier is not a UUID, and the database now treats it that way rather than leaving the bad value for a later query to trip over.
Things to watch for
- Existing data. Adding
UUID NOT NULLto a label that already has nodes with string identifiers will conflict with that data. Find and convert those nodes before you change the graph type, or add the property as optional first. - Mandatory means mandatory.
NOT NULLalso rejects nodes that omitidaltogether, not just nodes with the wrong type.
Comments (0)
Loading comments...