Describe the Bug
@payloadcms/drizzle rejects any JSON-field where query whose value contains non-ASCII characters (CJK, accented Latin, emoji,
etc.). The validation regex in src/utilities/escapeSQLValue.ts is:
export const SAFE_STRING_REGEX = /^[\w @.-+:]*$/
\w is ASCII-only ([A-Za-z0-9_]), so any string containing characters like 中, é, ü, あ, ñ, etc. fails the test and throws:
APIError: is not allowed as a JSON query value (status 400)
This is called from two paths:
- dist/queries/parseParams.js:152,154 — applies to every JSON-field query operator (equals, like, in, contains, etc.) across
both Postgres and SQLite adapters. - dist/postgres/createJSONQuery/index.js:23 and dist/sqlite/createJSONQuery/index.js.
For any project with internationalized data stored in a JSON / json / jsonb column, this makes JSON queries effectively unusable. We hit this on a Chinese-language deployment and have to ship a patch (patches/@payloadcms__drizzle@3.84.1.patch)
replacing the regex with a Unicode-aware version:
export const SAFE_STRING_REGEX = /^[\p{L}\p{N}\s@.-+:_]*$/u
\p{L} (any Unicode letter) and \p{N} (any Unicode number) with the /u flag still block SQL metacharacters (', ;, --, (, ), =, /,
, etc.) so the injection-prevention intent is preserved while allowing legitimate international text.
Expected behavior: JSON-field queries with non-ASCII values should succeed when the value contains only
letters/digits/whitespace and the existing safe punctuation set.
Actual behavior: Any non-ASCII letter or digit causes the query to throw a 400 APIError.
Link to the code that reproduces this issue
https://github.com/smoothdvd/payload-issues
Reproduction Steps
- Create a Payload project with the Postgres adapter (@payloadcms/db-postgres) and a collection containing a json field, e.g.:
// collections/Items.ts
import type { CollectionConfig } from 'payload'
export const Items: CollectionConfig = {
slug: 'items',
fields: [
{ name: 'meta', type: 'json' },
],
}
2. Seed a document:
await payload.create({
collection: 'items',
data: { meta: { title: '你好世界' } },
})
3. Query the JSON field with a non-ASCII value:
await payload.find({
collection: 'items',
where: { 'meta.title': { equals: '你好世界' } },
})
4. Observe the request throws:
APIError: 你好世界 is not allowed as a JSON query value
at escapeSQLValue (node_modules/@payloadcms/drizzle/dist/utilities/escapeSQLValue.js:14)
- The same failure occurs with like, contains, in, etc., and with any Unicode letter (café, naïve, Größe, 日本語, 한국어, …).
Environment
- payload@3.84.1
- @payloadcms/drizzle@3.84.1
- @payloadcms/db-postgres@3.84.1
- Node 20.x, PostgreSQL 16
Suggested fix
Swap the regex for the Unicode-aware variant shown above (or equivalent), and add a test covering CJK / accented input on JSON
queries.
Which area(s) are affected?
Not sure
Environment Info
Binaries:
Node: 22.22.2
npm: 10.9.7
Yarn: N/A
pnpm: 10.33.2
Relevant Packages:
payload: 3.84.1
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.4.0: Thu Mar 19 19:31:09 PDT 2026; root:xnu-12377.101.15~1/RELEASE_ARM64_T8132
Available memory (MB): 16384
Available CPU cores: 10
Describe the Bug
@payloadcms/drizzle rejects any JSON-field where query whose value contains non-ASCII characters (CJK, accented Latin, emoji,
etc.). The validation regex in src/utilities/escapeSQLValue.ts is:
export const SAFE_STRING_REGEX = /^[\w @.-+:]*$/
\w is ASCII-only ([A-Za-z0-9_]), so any string containing characters like 中, é, ü, あ, ñ, etc. fails the test and throws:
APIError: is not allowed as a JSON query value (status 400)
This is called from two paths:
both Postgres and SQLite adapters. - dist/postgres/createJSONQuery/index.js:23 and dist/sqlite/createJSONQuery/index.js.
For any project with internationalized data stored in a JSON / json / jsonb column, this makes JSON queries effectively unusable. We hit this on a Chinese-language deployment and have to ship a patch (patches/@payloadcms__drizzle@3.84.1.patch)
replacing the regex with a Unicode-aware version:
export const SAFE_STRING_REGEX = /^[\p{L}\p{N}\s@.-+:_]*$/u
\p{L} (any Unicode letter) and \p{N} (any Unicode number) with the /u flag still block SQL metacharacters (', ;, --, (, ), =, /,
, etc.) so the injection-prevention intent is preserved while allowing legitimate international text.
Expected behavior: JSON-field queries with non-ASCII values should succeed when the value contains only
letters/digits/whitespace and the existing safe punctuation set.
Actual behavior: Any non-ASCII letter or digit causes the query to throw a 400 APIError.
Link to the code that reproduces this issue
https://github.com/smoothdvd/payload-issues
Reproduction Steps
// collections/Items.ts
import type { CollectionConfig } from 'payload'
export const Items: CollectionConfig = {
slug: 'items',
fields: [
{ name: 'meta', type: 'json' },
],
}
2. Seed a document:
await payload.create({
collection: 'items',
data: { meta: { title: '你好世界' } },
})
3. Query the JSON field with a non-ASCII value:
await payload.find({
collection: 'items',
where: { 'meta.title': { equals: '你好世界' } },
})
4. Observe the request throws:
APIError: 你好世界 is not allowed as a JSON query value
at escapeSQLValue (node_modules/@payloadcms/drizzle/dist/utilities/escapeSQLValue.js:14)
Environment
Suggested fix
Swap the regex for the Unicode-aware variant shown above (or equivalent), and add a test covering CJK / accented input on JSON
queries.
Which area(s) are affected?
Not sure
Environment Info