Back

Loading…

Documentation

😵 Why Drupal Config Keeps Changing When “Nothing Changed”

Date: 2026-06-26

✨ Summary

If you run drush cst, drush cex, or compare config/sync against the active database config, Drupal can report differences even when nobody intentionally changed site behavior.

Sometimes the diff is real.

Sometimes it is only:

  • YAML key order changes
  • translated labels leaking into base config
  • langcode or config-language drift

This is a known Drupal pain point. It is not one single bug. It is a combination of:

  • configuration serialization details
  • multilingual config override behavior
  • config entities being saved in the current admin language

🧩 The Short Version

There are 3 main reasons this happens:

  1. Order-only serialization drift
  2. Language overrides leaking into base config
  3. Config language / langcode churn

So yes: this is a known Drupal issue family.

But the exact cause depends on the kind of diff you are seeing.


1. 🔀 Order-Only Serialization Drift

Sometimes Drupal stores the same config values in a different key order.

That means:

  • the meaning is unchanged
  • the behavior is unchanged
  • but the YAML file is different byte by byte

This is why drush cst can show a config item as “Different” even though the only change is the order of nested keys.

Typical examples

  • menu overrides where keys move around
  • field widget or drag/drop config where one nested item is moved lower in the file
  • display/form config where maps are serialized in a slightly different order

Current example from this project

The recent drush cst output showed:

  • core.menu.static_menu_link_overrides
  • field.field.node.page.field_paragraphs

In both cases, the values were the same. Only the YAML order differed.

That is harmless config drift, not a functional site change.

Relevant Drupal core issue

  • #2852557 Config export key order is not predictable, use config schema to order keys for maps
    • Status: Closed (fixed)
    • Link: https://www.drupal.org/project/drupal/issues/2852557

This issue fixed a lot of ordering instability in core, but not every possible nested save path or contrib interaction.

Related issue

  • #3480248 Drupal does not recognize when the config is identical
    • Link: https://www.drupal.org/project/drupal/issues/3480248

This is closely related to the same general class of problem: Drupal still sometimes treats semantically identical config as different.


2. 🌍 Language Overrides Leaking Into Base Config

Drupal has a configuration override system.

One important override type is language overrides.

That is a useful feature, but it becomes dangerous when a config entity is loaded with overrides active and then saved back into the original storage.

When that happens, translated labels can leak into the base config.

What this looks like in real life

You translate something in German, French, or Dutch.

Then later:

  • a block is saved
  • a View is edited
  • a menu item is reordered
  • a field or display config entity is saved

And suddenly the exported base config contains translated labels or changed values in the “wrong” language.

Why it happens

Drupal’s config system conceptually separates:

  • loading config with overrides
  • loading editable config that should be saved

But in practice, config entities can still be saved after being loaded with overrides, and that causes override values to be written back to the original config.

Relevant Drupal core issue

  • #2910353 Prevent saving config entities when configuration overrides are applied
    • Status as of 2026-06-26: Needs work
    • Link: https://www.drupal.org/project/drupal/issues/2910353

This is one of the most important issues behind config-language drift and translated-label corruption.

Related duplicate issue

  • #3117709 Avoid mixed languages in configuration sync
    • Status: Closed (duplicate)
    • Duplicate of #2910353
    • Link: https://www.drupal.org/project/drupal/issues/3117709

3. 🏷️ Config Language / langcode Churn

Another class of problem is when configuration language changes unexpectedly.

This often happens on multilingual sites when:

  • a module is installed
  • a theme is installed
  • the site default language is not English
  • development is done in a translated admin interface

Common symptom

You create fields or config in one language, export config, and later:

  • labels are exported in another language
  • langcode changes
  • extra language-specific config appears
  • config that used to look stable suddenly looks mixed

Relevant Drupal core issue

  • #3150540 Configuration langcode is forced to site default language
    • Status as of 2026-06-26: Needs work
    • Link: https://www.drupal.org/project/drupal/issues/3150540

This issue is especially relevant for teams that want a single canonical config language, often English, even when the site default language is something else.


📚 Useful Core Documentation

Configuration management

  • Drupal configuration management docs:
    • https://www.drupal.org/docs/administering-a-drupal-site/configuration-management

Configuration override system

  • Drupal configuration override system docs:
    • https://www.drupal.org/docs/drupal-apis/configuration-api/configuration-override-system

This is especially relevant because language overrides are stored as configuration too, and they are part of the bigger story here.


🧪 Important Clarification About drush cst

drush cst is read-only.

It does not create changes.

It only compares:

  • active config in the database
  • sync config in config/sync

So if drush cst reports differences, that means drift already exists.

It does not mean cst caused the drift.


✅ Can We Prevent It Completely?

No, not completely.

But we can reduce it a lot.


🛡️ Best Practices To Reduce Config Noise

1. Choose one canonical config language

Pick one admin/config language for structural work.

Usually:

  • English

This does not mean the site frontend must be English.

It means the team treats one language as the source-of-truth language for config authoring.


2. Do config work only in that language

Avoid saving config entities while using a translated admin UI if your team expects config exports to stay in one canonical language.

That includes editing:

  • fields
  • form displays
  • view displays
  • menus
  • Views
  • blocks
  • paragraph types

3. Use one environment as the config-authoring source of truth

A healthy workflow is:

  • one designated environment or branch is used to create/export config
  • other environments mostly import config

In practice:

  • on dev/stage/prod that should follow the repo: use drush cim
  • only on the config-authoring workflow: use drush cex

That reduces accidental export churn from random environments.


4. Be careful after module or theme installs

On multilingual sites, module/theme installs are common moments for config language churn.

After installs:

  • inspect drush cst
  • inspect git diff
  • do not assume all exported changes are intentional

5. Do not hide structural config drift with ignore rules

It is tempting to use ignore/split/filter modules to hide noisy config.

That can be valid for true environment-specific config.

But for structural config like:

  • field definitions
  • menus
  • display config

ignoring it usually hides real problems instead of solving them.


6. Review config diffs before exporting or committing

This sounds obvious, but it matters more in Drupal than in many frameworks.

A good habit:

  1. run drush cst
  2. inspect the exact files
  3. decide whether the differences are:
    • functional changes
    • order-only drift
    • translation/langcode noise

Only then decide whether to:

  • import sync config
  • export active config
  • or discard UI changes

7. Treat “translated labels in config” as suspicious

If your team expects canonical English config, and suddenly a label appears in German or French, that is usually not random.

It often means:

  • config was created in another admin language
  • a config entity was saved with language overrides active
  • multilingual behavior leaked into base config

That is worth investigating before committing.


🔎 A Practical Rule Of Thumb

When config changes appear, ask:

Is this a real behavior change?

Examples:

  • new field
  • new paragraph bundle
  • changed route settings
  • changed enabled/disabled flags
  • changed IDs/slugs/query values

If yes, it is probably intentional config work.

Or is this only serialization/language noise?

Examples:

  • same keys, different order
  • same values, different line order
  • label text switched language
  • langcode changed unexpectedly

If yes, it is probably Drupal config drift, not product work.


🧭 What To Do When You See Drift

If the repository is the source of truth:

ddev drush cim -y
ddev drush cst

If the database state is intentionally the new source of truth:

ddev drush cex -y

But that second option should only happen when you are sure the active config changes were intentional.


🧱 Final Takeaway

Drupal config drift is real, common, and often confusing. 😅

The most important things to remember are:

  • not every config diff is a real site change
  • drush cst does not create drift, it only reports it
  • multilingual admin/config workflows are a major source of noise
  • there are real, known core issues behind this behavior
  • you can reduce the problem with discipline, but not fully eliminate it

The most useful mental model

Think of Drupal config drift as a mix of:

  • serialization noise 🧾
  • multilingual override leakage 🌍
  • config-entity save behavior 🛠️

Once you separate those three categories, the diffs become much easier to reason about.


🔗 Reference Links

  • Drupal config management docs
    https://www.drupal.org/docs/administering-a-drupal-site/configuration-management

  • Drupal configuration override system docs
    https://www.drupal.org/docs/drupal-apis/configuration-api/configuration-override-system

  • #2852557 Config export key order is not predictable, use config schema to order keys for maps
    https://www.drupal.org/project/drupal/issues/2852557

  • #3480248 Drupal does not recognize when the config is identical
    https://www.drupal.org/project/drupal/issues/3480248

  • #2910353 Prevent saving config entities when configuration overrides are applied
    https://www.drupal.org/project/drupal/issues/2910353

  • #3117709 Avoid mixed languages in configuration sync
    https://www.drupal.org/project/drupal/issues/3117709

  • #3150540 Configuration langcode is forced to site default language
    https://www.drupal.org/project/drupal/issues/3150540

Contents