payload
payload copied to clipboard
Potential Bug: Refresh token API endpoint returns 500 with cast error
Describe the Bug
When attempting to use the built in auth 'refresh token', if your auth collection has a populated relationship field, the refresh response will be a server 500 error with a cast error. I am using the latest Payload and just tested on a fresh install. Also using MongoDB as the database.
I should also add I have tested on both Windows and MacOS.
Link to the code that reproduces this issue
https://github.com/paper-krane/test-refresh-token
Reproduction Steps
- Launch Payload Server
- Create a user at the 'users' collection endpoint. I have both users and admins in this app.
- Create a product (easiest to do so from admin).
- Populate the users 'productOwned' field with the product just created.
- Login as the user (not admin). I have been using Postman to test this particular bug out.
- Try to refresh token.
- Error should be returned.
Which area(s) are affected? (Select all that apply)
Not sure
Environment Info
Binaries:
Node: 24.2.0
npm: N/A
Yarn: N/A
pnpm: N/A
Relevant Packages:
payload: 3.47.0
next: 15.3.2
@payloadcms/db-mongodb: 3.47.0
@payloadcms/email-nodemailer: 3.47.0
@payloadcms/graphql: 3.47.0
@payloadcms/next/utilities: 3.47.0
@payloadcms/payload-cloud: 3.47.0
@payloadcms/richtext-lexical: 3.47.0
@payloadcms/translations: 3.47.0
@payloadcms/ui/shared: 3.47.0
react: 19.1.0
react-dom: 19.1.0
Operating System:
Platform: win32
Arch: x64
Version: Windows 11 Home
Available memory (MB): 65430
Available CPU cores: 64
I can confirm this also occurs with Postgres.
I don't love this solution but for now I was able to continue using the standard refresh token by adding the following hook to the authorized collection.
hooks: {
afterRead: [
async ({ doc }) => {
// Normalize relationship fields to only contain IDs after reading from database
// This ensures that when the user is read and then passed to db.updateOne() in refresh,
// the relationships are IDs and not populated objects
if (doc.productOwned) {
doc.productOwned = doc.productOwned.map((product: any) =>
typeof product === 'number' ? product : product.id,
)
}
return doc
},
],