Hi, I have a problem that I tried my best to fix in all ways possible.
I get a "You are not allowed to perform this action." on every document creation on all collections.
- I tried removing node_modules, pnpm store prune reinstall
- changing to version 3.28.1, 3.27.0, 3.26.0
- pnpx payload migrate:fresh, retry with fresh first user
Here's the shortened stack trace server error :
Request cookies: payload-token=REDACTED => middleware shows token in request
Request path: /admin/collections/media/create
{
"level": 50,
"time": 1742071317956,
"pid": 3134,
"hostname": "podmax",
"name": "payload",
"err": {
"type": "Error",
"message": "Unauthorized",
"stack": "Error: Unauthorized
at buildFormStateHandler (webpack-internal:///(rsc)/./node_modules/.pnpm/@payloadcms+ui@3.27.0_@types+react@19.0.10_monaco-editor@0.52.2_next@15.2.2_react-dom@1_1d4e4886e2c7f189dd15bb7272ea78a8/node_modules/@payloadcms/ui/dist/utilities/buildFormState.js:53:15)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async /root/podmax/node_modules/.pnpm/next@15.2.2_react-dom@19.0.0_react@19.0.0__react@19.0.0_sass@1.77.4/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:438:2357
at async handleAction
[...]
"msg": "There was an error building form state"
}after this error the request is replied with 403. in file upload, the error (see image) is showed as soon as file is in dropzone.
it works with :
curl 'https://redacted/api/media?depth=0&fallback-locale=null' -X POST -H 'Cookie: payload-token=redacted' -F '_payload={"alt": "My image description"}' -F 'file=./fichiers.png'so the problem happens only when I'm using the web interface.
the next dev server is on alpine if that's relevant.
can someone help me 🙏 ? this is a very worrying problem, happens just as I am testing my production server for mondays deadline... I'll do whatever you want
please 😭
this usually has something to do with the cors or csrf. Make sure your next middle ware is setup for the correct domains and also the payload config
cors & csrfcors: allowedOrigins,
csrf: allowedOrigins,const allowedOrigins = [process.env.NEXT_PUBLIC_SERVER_URL].filter(Boolean);i have a nginx reverse proxy in front of it it may be why, thank you so much i'll try that now
add this to the payload config and add any domains that might be accessing the panel into the allowOrigins array
yeah, usually with any non regular setup where you have subdomains or another type of setup where the expected domain differs from where your accessing it from will give this type of error.
also makesure to configure your next middleware as well
thank you so much i was so stressed i'm feeling better
i'll try now i'll mention you if i cant find syntax
or something
anytime, ping me if you need
thank you so much !!
seems like I'm not doing it well...
payload config =
const allowedOrigins = [
process.env.NEXT_PUBLIC_BASE_URL,
process.env.NEXT_PUBLIC_BASE_URL_ADMIN,
'http://localhost:3000',
'http://10.0.0.102:3000',
].filter(Boolean)
export default buildConfig({
...
},
cors: allowedOrigins,
csrf: allowedOrigins,middleware.ts =
import { type NextRequest, NextResponse } from 'next/server'
import { updateSession } from '@/utils/supabase/middleware'
export async function middleware(request: NextRequest) {
// Log cookies before processing
console.log('Request cookies:', request.headers.get('cookie'));
// Log the URL path to help identify which routes are being processed
console.log('Request path:', request.nextUrl.pathname);
const response = await updateSession(request)
// Add CORS headers
response.headers.set('Access-Control-Allow-Origin', 'https://myproductionserver.fr, http://127.0.0.1:3000, http://10.0.0.102:3000')
response.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
response.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization')
response.headers.set('Access-Control-Allow-Credentials', 'true')
// Add CSRF protection headers
response.headers.set('X-Frame-Options', 'DENY')
response.headers.set('X-Content-Type-Options', 'nosniff')
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
response.headers.set('Cross-Origin-Opener-Policy', 'same-origin')
return response
}
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
* Feel free to modify this pattern to include more paths.
*/
'/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|glb)$).*)',
],
}isnt this what you expected ?
ok thats a good start, is that not working for you yet? still same unauthorized errors?
and this is coming from when you access it via the web interface? and whats the domain for the web interface?
still the same errors, even after deleting node_modules .next, creating first user again.
errors happen when loading a file in an upload collection dropzone, and 403 response when hitting save
the web interface does not have a separate domain its the auto complete that created two env variables ^^'
the 10.0.0.102 is the final destination, the ssl cert A record points to the nginx reverse proxy main server, which matches the cert and proxies the request to 10.0.0.102:3000
i see and in the url for the webinterface your at
http://10.0.0.102:3000?
i don't understand what you mean i'm testing the web interface being correctly proxied so the url in my browser is the production server domain name, when starting pnpm dev I can see
Network: http://10.0.0.102:3000as expected, the nginx reverse proxy sits in between and proxies all the headers
https://prodname.com/admin -> http://10.0.0.102:3000/adminis happenign correctly
ah yes so the url is the production server domain.
const allowedOrigins = [
process.env.NEXT_PUBLIC_BASE_URL,
process.env.NEXT_PUBLIC_BASE_URL_ADMIN,
'http://localhost:3000',
'http://10.0.0.102:3000',
'https://productionserver.domain',
].filter(Boolean)make sure thats in here
🫡
worked ! wtf that's weird NEXT_PUBLIC_BASE_URL was supposed to be it
these allowedOrigins should also be the same as what your using in the next middleware aswell. I would probably export that array so that you can reuse it.
yea
do you have a kofi ?
well glad it worked for you, if NEXT_PUBLIC... was supposed to be it then i would also check your env vars are being loaded correctly as maybe thats why it wasnt working
haha no, and no need, just here to support the community and get it back when i need
i'll look into it
tysm i'll try to help around too
dm me if u need anything
Star
Discord
online
Get dedicated engineering support directly from the Payload team.