payloadcms / payloadcms/payload
REST API returns inconsistent query parameter types in req depending on endpoint
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
When making requests to different REST API endpoints, query parameters are parsed into the req object with inconsistent types. The same query parameter can appear as different types (e.g. string vs number) depending on which endpoint handles the request.
In this example you can see that we have two request:
- /api/query-param-types?limit=10&draft=true
req.query.limit is a type of number
req.query.draft is a type of boolean
- /api/query-param-types/1?limit=10&draft=true
req.query.limit is a type of string
req.query.draft is a type of string
This check is happening in the read access control in a collection:
const readAccess: Access = ({ req }) => {
if ('limit' in req.query) {
req.payload.logger.info(`Limit Type: ${typeof req.query.limit}`)
}
if ('draft' in req.query) {
req.payload.logger.info(`Draft Type: ${typeof req.query.draft}`)
}
return true
}
Expected Behavior
Query parameter values should be handled consistently across all REST API endpoints. All query parameters should either be returned as strings, or they should be reliably cast to their correct data types (such as numbers and booleans).
Link to the code that reproduces this issue
Reproduction Steps
- Add the following read access control to a collection:
const readAccess: Access = ({ req }) => {
if ('limit' in req.query) {
req.payload.logger.info(`Limit Type: ${typeof req.query.limit}`)
}
if ('draft' in req.query) {
req.payload.logger.info(`Draft Type: ${typeof req.query.draft}`)
}
return true
}
- Start the Payload server
- Make a request to the collection root endpoint with query parameters
/api/{collection}?limit=10&draft=true - Observe the server logs:
req.query.limit is logged as type number
req.query.draft is logged as type boolean - Make a request to a single document endpoint in the same collection using identical query parameters:
/api/{collection}/{id}?limit=10&draft=true - Observe the server logs:
req.query.limit is logged as type string
req.query.draft is logged as type string
Which area(s) are affected?
area: core
Environment Info
Binaries:
Node: 20.11.0
npm: 10.2.4
Yarn: 1.22.22
pnpm: 10.6.4
Relevant Packages:
payload: 3.70.0
next: 15.4.10
@payloadcms/db-postgres: 3.70.0
@payloadcms/drizzle: 3.70.0
@payloadcms/graphql: 3.70.0
@payloadcms/next/utilities: 3.70.0
@payloadcms/richtext-lexical: 3.70.0
@payloadcms/translations: 3.70.0
@payloadcms/ui/shared: 3.70.0
react: 19.2.1
react-dom: 19.2.1
Operating System:
Platform: darwin
Arch: arm64
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 the reproduction in QueryParamTypes.ts and compare query handling for the collection root and single-document REST endpoints, using the read access control as the observation point. Trace where req.query is populated for each entry point; done means identical query parameter types are reported for both requests, with regression coverage for the reproduced cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100