Skip to content

enableGlobalContextStore: false is ignored at runtime when the server config node has no version property (migration v5 forces it back to true) #2024

Description

@hckroeger

Describe the bug

Disabling "Enable global context store" in the server config node has no effect at runtime if the stored config node in flows.json does not contain a version property. The palette keeps writing all entity states to global.homeassistant on every state change, even though the deployed config clearly contains "enableGlobalContextStore": false.

Root cause (verified against the v0.80.3 sources):

  1. On startup, config-server/index.ts runs the stored config through migrate(config):

    this.config = migrate(config);
  2. src/helpers/migrate.ts only skips migrations when a version property exists:

    if (schema.version !== undefined && schema.version >= currentVersion) {
        return schema;
    }

    If version is undefined (which is the case for server config nodes created before the versioning mechanism was introduced and apparently never backfilled on save), all migrations from 0 to 6 are re-applied on every startup.

  3. Migration version 5 in src/nodes/config-server/migrations.ts sets the flag unconditionally, overwriting whatever the user configured:

    {
        version: 5,
        up: (schema: any) => {
            const newSchema = {
                ...schema,
                version: 5,
                enableGlobalContextStore: true,
            };
            return newSchema;
        },
    },
  4. The migrated config is only used in memory and never written back to flows.json, so the editor and the deployed flows keep showing false while the running node behaves as if it were true. There is no visible indication of the mismatch.

Note that other migrations do get reflected in the saved config when the node is edited (e.g. ha_boolean was converted from "" to [] on my instance), but the version property itself was never persisted, so the runtime migration keeps re-running forever.

Impact

This is mostly invisible with the default in-memory context store. It becomes a real problem when a persistent context store is configured (contextStorage: { default: { module: "localfilesystem" } }): the full entity/state mirror (>1 MB on a typical installation, updated on every state change) is then flushed to disk continuously — unnecessary flash wear and CPU on typical Home Assistant hardware — and there is no way to turn it off via the UI.

To Reproduce

  1. Use a server config node whose entry in flows.json has no version property (legacy node; removing the property manually reproduces it as well).
  2. Open the server config, untick Enable global context store, deploy, restart Node-RED.
  3. Open the context sidebar → Global: homeassistant is (re)created and grows with every state change.
  4. Delete the homeassistant key in the context sidebar → it is immediately repopulated.
  5. Verify via the admin API (GET /flows) that the deployed config really contains "enableGlobalContextStore": false.

Expected behavior

  • A migration must not overwrite an explicitly configured value; migration v5 should only set a default when the property is absent, e.g.

    enableGlobalContextStore: schema.enableGlobalContextStore !== undefined
        ? schema.enableGlobalContextStore
        : true,
  • Additionally/alternatively: ensure the version property is persisted when a config node is saved from the editor, so runtime migrations don't silently re-run on every start.

Screenshots

No response

Example Flow

Environment Information

  • node-red-contrib-home-assistant-websocket: 0.80.3
  • Node-RED: v5.0.0 (Home Assistant Community Add-on v22.0.0)
  • Node.js: v24.16.0
  • Home Assistant: 2026.6.4
  • Context storage: localfilesystem as default store (memory default hides the symptom)

Additional context

Workaround

Warning

Adding version alone can break your flows: it stops all migrations from running, so any field in your stored config that still relies on a migration default will be used raw. In my case "ha_boolean": [] (previously fixed up by migration v1 on every start) caused all boolean state matching to silently fail — motion sensors, smoke detectors etc. stopped triggering.

Safe procedure:

  1. Stop Node-RED, back up flows.json.
  2. On the server config node, add "version": 6 and make sure the migration-provided fields hold sane values — most importantly "ha_boolean": ["y", "yes", "true", "on", "home", "open"] (must not be empty). The status* and *Selector fields from migrations v3/v4 have code-side fallbacks and are uncritical.
  3. Start Node-RED, delete the stale homeassistant key via the context sidebar (Global scope).
  4. Verify: the key stays deleted, and boolean-based state nodes still trigger.

After this, the setting is honored and the context store remains clean.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions