You started Strapi, the terminal banner says development, and the admin panel disagrees:
Strapi is in production mode, editing content types is disabled. Please switch to development mode by starting your server with
strapi develop.
You set NODE_ENV=development in .env. You exported it in your shell. The startup log still says development. The Content-Type Builder is still read-only.
The rule
Two independent things are being conflated, and Strapi checks the one people do not think about.
NODE_ENV: the conventional Node environment variable. It controls whichconfig/env/<env>/folder is loaded and shows up in the startup banner and in the admin panel's environment display.- Which command you ran:
strapi developversusstrapi start. This is what actually gates the Content-Type Builder.
The Content-Type Builder requires strapi develop. It is enabled by the command, not by NODE_ENV. Setting NODE_ENV=development while running strapi start gives you exactly the contradiction above: a banner that says development and an admin panel that behaves like production.
Concretely, every Content-Type Builder write route sits behind one middleware that checks a single config value:
// packages/core/content-type-builder/server/src/middlewares/is-development-mode.ts
const autoReload = strapi.config.get('autoReload');
if (autoReload !== true) {
throw new errors.PolicyError(
'Content-Type Builder modifications are disabled in production mode. ' +
'Schema changes can only be made when running with autoReload enabled (strapi develop).'
);
}autoReload is not something you set in a config file. strapi develop sets it to true when it creates the Strapi instance, and strapi start leaves it false. That is the entire rule. NODE_ENV is not read here.
The reason is structural. The Content-Type Builder writes schema.json files to disk, and Node has to restart for those changes to take effect. strapi develop runs a file watcher that restarts the server on change. strapi start does not, so allowing schema edits there would write files that never load, or would require killing your production process on every save. Strapi disables the feature instead.
The fix
Run the right command:
npm run develop
# or
yarn develop
# or
npx strapi developCheck what your package.json scripts actually do:
{
"scripts": {
"develop": "strapi develop",
"start": "strapi start",
"build": "strapi build"
}
}If develop has been edited to run strapi start, or if you have been typing npm start out of habit, that is the whole problem. npm start runs the start script, which is production mode, regardless of NODE_ENV.
If npm run develop still does not work
A frequent report, including in the original forum thread, is that npm run develop behaves like production while npx strapi develop works. When that happens, one of these is true:
NODE_ENV=production is set in your environment
This will not by itself lock the Content-Type Builder. The autoReload gate above is the only server-side check, and strapi develop sets it regardless of NODE_ENV. What NODE_ENV=production does do is make the admin panel report the environment as production (which is also what hides the Strapi AI assistant in the Content-Type Builder), load your config/env/production/ overrides, and change Node's own behaviour. So it is worth clearing when the panel and the terminal disagree, and it is frequently a symptom of the real problem: an npm wrapper, Dockerfile, or CI image that is also rewriting which command runs.
Find where it is coming from:
# Your current shell
echo $NODE_ENV
# The .env Strapi loads
grep NODE_ENV .env
# Shell profile
grep -rn "NODE_ENV" ~/.zshrc ~/.bashrc ~/.profile 2>/dev/null
# The scripts themselves
grep -n "NODE_ENV" package.jsonThen either unset it or set it explicitly for the command:
unset NODE_ENV
npm run develop
# or, one-off
NODE_ENV=development npx strapi developOn Windows, NODE_ENV=development npm run develop does not work in cmd or PowerShell, because the syntax is POSIX. Use cross-env:
npm install --save-dev cross-env{
"scripts": {
"develop": "cross-env NODE_ENV=development strapi develop"
}
}An npm wrapper or .npmrc is injecting it
Some CI images, Dockerfiles, and .npmrc files set NODE_ENV=production globally, often to make npm install skip devDependencies. That leaks into every npm run in that environment.
npm config get production
cat .npmrc 2>/dev/null
cat ~/.npmrc 2>/dev/nullYou are running it inside a container built for production
If your Dockerfile has ENV NODE_ENV=production, everything inside that container is production, whatever you type. Use a separate development target, or override at run time:
docker compose run -e NODE_ENV=development strapi npm run developWhy you should not force this in a deployed environment
Every so often someone wants the Content-Type Builder available on a shared staging server. Strapi does not support it, and the reasons are worth stating plainly:
- Schema files are code. They live in
src/api/*/content-types/*/schema.jsonand belong in source control. A content type created on the server exists only there and is overwritten by the next deploy. - The schema sync deletes things. On startup Strapi compares the content-types schemas with the database and drops tables, columns, and indexes that no longer match. A schema created on the server and absent from the repository is dropped on the next release, along with its data, without a prompt.
- It requires restarts. Every schema change restarts the Node process. On a shared environment that is a small outage every time someone adds a field.
The supported workflow is: build content types locally → commit → deploy → use Data Transfer to move content between environments. The Strapi FAQ is explicit that there is no plan to allow content-type editing in production and no recommended workaround.
Sanity checklist
| Check | Expected |
|---|---|
| Command | strapi develop, not strapi start |
echo $NODE_ENV | empty or development |
grep NODE_ENV .env | absent or development |
package.json develop script | strapi develop |
Not inside a container with ENV NODE_ENV=production | n/a |
| Windows | using cross-env |
If all six are right and the Content-Type Builder is still locked, restart cleanly: kill the process, delete .strapi and dist, and run npm run develop again. A stale build directory can serve an admin bundle built in production mode.




