Using UUID properties in a Neo4j graph type

Neo4j 2026.08 added a UUID type. Declare it in a graph type, generate values with uuid(), and let the database reject anything else.

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.

Graph Type Schema Enforcement

Define and enforce a Neo4j graph schema with graph types: typed nodes and relationships, KEY and UNIQUE constraints, and incremental evolution.

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:

cypher
ALTER CURRENT GRAPH TYPE SET {
  (:Thing => {
    id :: UUID NOT NULL,
    name :: STRING
  })
}

Check what the database stored:

cypher
SHOW CURRENT GRAPH TYPE
text
(:`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:

cypher
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:

cypher
CREATE (:Thing {id: 'abc'})

The database rejects it:

text
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 NULL to 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 NULL also rejects nodes that omit id altogether, not just nodes with the wrong type.

Comments (0)

Loading comments...