Skip to content

[5.x]: Plugin store fails to load if the environment variable for a license key is missing #17942

@MoritzLost

Description

@MoritzLost

What happened?

Description

We use environment variables to set the license keys for Craft itself, and for all commercial plugins:

CRAFT_LICENSE_KEY=[redacted]
PLUGIN_LICENSE_KEY_FORMIE=[redacted]
PLUGIN_LICENSE_KEY_RETOUR=[redacted]

Sometimes, new plugins are added during development. In this case, we add the new environment variable (without a value) to the .env.example file. But not all environments (dev, staging or prod) will immediately have this variable in the .env file.

If the environment variable is set in the .env file, Craft creates a license key and writes it to that file when either Settings -> Plugins or the Plugin Store are visited in the Control Panel. This is as expected and convenient.

The problem is what happens when the environment variable does not exist at all in the .env file. In this case, Craft attempts to modify the project config to overwrite the environment variable with a hard-coded key. This leads to two problems:

Plugin store fails to display in production environments

In the production environment, the scenario above results in an error because the project config is read-only, and the plugin store fails to load:

Image
2025-10-13 11:32:02 [web.ERROR] [yii\base\NotSupportedException] Changes to the project config are not possible while in read-only mode. {"trace":["#0 /path/to/project/vendor/craftcms/cms/src/services/ProjectConfig.php(526): craft\\services\\ProjectConfig->_setInternal()","#1 /path/to/project/vendor/craftcms/cms/src/services/Plugins.php(1193): craft\\services\\ProjectConfig->set()","#2 /path/to/project/vendor/craftcms/cms/src/helpers/Api.php(203): craft\\services\\Plugins->setPluginLicenseKey()","#3 /path/to/project/vendor/craftcms/cms/src/controllers/AppController.php(172): craft\\helpers\\Api::processResponseHeaders()","#4 [internal function]: craft\\controllers\\AppController->actionProcessApiResponseHeaders()","#5 /path/to/project/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array()","#6 /path/to/project/vendor/yiisoft/yii2/base/Controller.php(178): yii\\base\\InlineAction->runWithParams()","#7 /path/to/project/vendor/yiisoft/yii2/base/Module.php(552): yii\\base\\Controller->runAction()","#8 /path/to/project/vendor/craftcms/cms/src/web/Application.php(360): yii\\base\\Module->runAction()","#9 /path/to/project/vendor/craftcms/cms/src/web/Application.php(659): craft\\web\\Application->runAction()","#10 /path/to/project/vendor/craftcms/cms/src/web/Application.php(322): craft\\web\\Application->_processActionRequest()","#11 /path/to/project/vendor/yiisoft/yii2/base/Application.php(384): craft\\web\\Application->handleRequest()","#12 /path/to/project/web/index.php(10): yii\\base\\Application->run()","#13 {main}"],"memory":4056824,"exception":"[object] (yii\\base\\NotSupportedException(code: 0): Changes to the project config are not possible while in read-only mode. at /path/to/project/vendor/craftcms/cms/src/services/ProjectConfig.php:554)"} 
2025-10-13 11:32:10 [web.WARNING] [craft\services\Updates::getUpdates] Couldn't get updates: Changes to the project config are not possible while in read-only mode. {"memory":4341480} 

Unwanted changes to the project config

We very often get those unwanted changes to the project config where the licenseKey for a plugin, which we have defined through an environment variable like $PLUGIN_LICENSE_KEY_FORMIE, is replaced with a hardcoded license key. This happens every time a new commercial plugin is added, and any developer on the team forgets to add the new environment variable to their .env file.

Steps to reproduce

  1. Install a commercial plugin and set the license key to an environment variable that exists in the .env.
  2. Remove the environment variable from the .env file.
  3. Open the plugin store in production mode.

Expected behavior

If a plugin license key is set to an environment variable, Craft should never attempt to replace that with a hardcoded key. It should continue to operate without a license key, or if that is not possible, explicitly throw an error that informs the user of the problem.

Actual behavior

See above.

Craft CMS version

5.8.18

PHP version

8.3

Operating system and version

No response

Database type and version

No response

Image driver and version

No response

Installed plugins and versions

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions