payloadcms / payloadcms/payload
Invalid UUID in treated as IS NULL and returns incorrect data
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 44.8k
- Forks
- 4.2k
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 53
Description
Describe the Bug
Invalid UUID values in an equals filter appear to be sanitized to null, which then changes the meaning of the query to IS NULL.
We noticed this with a UUID relationship field, but this may affect UUID columns more generally.
In our case:
equals: "<valid UUID with matching documents>"returns the correct documents.equals: "<valid UUID with no matching documents>"returns an emptydocsarray.equals: "invalid-something"returns documents where the relationship field isnull.
We are not fully sure what the intended behavior should be. Possible expected behavior could be:
- Throw a query validation error because
"invalid-something"is not a valid UUID. - Return no results, matching the behavior of a valid UUID that simply does not match anything.
But returning documents where the field is null seems unexpected, because the caller asked for equals: "invalid-something", not equals: null.
This may be related to the UUID sanitization added in #8369.
In @payloadcms/drizzle, sanitizeQueryValue appears to convert invalid UUID strings to null:
if (isUUID && typeof formattedValue === 'string') {
if (!uuidValidate(val)) {
formattedValue = null
}
}
Then later in parseParams, equals with a null query value is interpreted as IS NULL:
if (operator === 'equals' && queryValue === null) {
constraints.push(isNull(resolvedColumn))
break
}
So the effective query becomes "column is null".
There also seems to be a related issue when multiple operators are provided on the same field. If equals is processed first and becomes IS NULL, the break means another operator like exists: true may not be applied.
Link to the code that reproduces this issue
https://github.com/tobiasvdorp/payload-uuid-treated-as-null-issue-repro
Reproduction Steps
- Create a collection with a relationship field:
{
name: 'articleType',
type: 'relationship',
relationTo: 'article-types',
hasMany: false,
}
- Configure Postgres with UUID ids:
postgresAdapter({
idType: 'uuid',
})
-
Create at least one document where the relationship field is empty (
null). -
Query with a syntactically valid UUID that has no matching documents. This returns an empty
docsarray as expected:
query {
Articles(
where: {
articleType: {
equals: "valid-article-type-uuid" // replace with actual UUID of existing articleType
}
}
) {
docs {
id
articleType {
id
}
}
}
}
- Query with a value that is not a valid UUID:
query {
Articles(
where: {
articleType: {
equals: "invalid-something"
}
}
) {
docs {
id
articleType {
id
}
}
}
}
-
Observe that the query returns documents where
articleTypeisnull. -
Optionally add
exists: trueon the same field:
query {
Articles(
where: {
articleType: {
equals: "invalid-something"
exists: true
}
}
) {
docs {
id
articleType {
id
}
}
}
}
- Observe that this does not appear to prevent the
nullrelationship documents from being returned in our case.
Which area(s) are affected?
area: graphql, area: core, db: postgres, db: mongodb
Environment Info
Binaries:
Node: 22.17.1
npm: 10.9.2
Yarn: N/A
pnpm: 10.33.0
Relevant Packages:
payload: 3.82.1
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.3.0: Wed Jan 28 20:53:15 PST 2026; root:xnu-12377.81.4~5/RELEASE_ARM64_T6000
Available memory (MB): 32768
Available CPU cores: 10
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with sanitizeQueryValue in @payloadcms/drizzle and follow parseParams, comparing invalid UUID handling with equals and exists. Use the linked reproduction to verify behavior for PostgreSQL and MongoDB, then confirm the intended outcome for invalid UUIDs and ensure the result no longer treats them as IS NULL.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- graphql, mongodb, postgresql, typescript
- Domain
- api, backend, databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100