9 – Configuration overrides have unpredictable results

I’m setting up configuration splits with Drupal 9 (in DDEV-Local, if that matters) and encountering unexpected results.

(Note: I understand if config_split is off-topic here since it is not a core module, but I’m still hoping that someone will see the question and offer an insight.)

None of my splits are marked as “Active” in the active configuration or the exported configuration YAML. I want to set the default Local split in settings.php and then use settings.local.php to override it on dev, stg, prd environments.

(In case it is relevant, I can’t use environment variables to differentiate the dev, stg, prd environments since they are all on one host, in different Apache VirtualHosts.)

This is the default override in settings.php:

  $config('config_split.config_split.local')('status') = TRUE;
  $config('config_split.config_split.prd')('status') = FALSE;
  $config('config_split.config_split.stg')('status') = FALSE;
  $config('config_split.config_split.dev')('status') = FALSE;

So far, so good. The Local split is “active (overwritten)”.

Things get weird when I edit this to enable another split in my Local environment:

  $config('config_split.config_split.local')('status') = FALSE;
  $config('config_split.config_split.prd')('status') = TRUE;
  $config('config_split.config_split.stg')('status') = FALSE;
  $config('config_split.config_split.dev')('status') = FALSE;

After editing settings.php (and clearing cache, of course) the Production split is “active (overwritten)”, as expected.

Unfortunately, the Local split is also “active (overwritten)” despite setting its ('status') = FALSE;,

Things get weirder when I attempt to logically negate the values of all the splits:

  $config('config_split.config_split.local')('status') = FALSE;
  $config('config_split.config_split.prd')('status') = TRUE;
  $config('config_split.config_split.stg')('status') = TRUE;
  $config('config_split.config_split.dev')('status') = TRUE;

Now, the Local split is still “active (overwritten)” despite setting its ('status') = FALSE;,

The Stage and Production splits are “active (overwritten)” to match their ('status') = TRUE;,

And the Dev split remains “inactive” despite setting its ('status') = TRUE;,

Any idea what is happening here?