Gracefully handle deprecated telemetry config#266029
Conversation
|
/ci |
|
/ci |
💚 Build Succeeded
Metrics [docs]
History
cc @eokoneyo |
|
FYI: There was also a forum post on this issue a while back: Elastic Security is missing in kibana [9.0.2] |
|
Pinging @elastic/kibana-core (Team:Core) |
Yes we are aware, this fix will be applied to all affected versions after it merges. |
|
Starting backport for target branches: 8.19, 9.2, 9.3, 9.4 https://github.com/elastic/kibana/actions/runs/25064030767 |
💔 Some backports could not be created
Note: Successful backport PRs will be merged automatically after passing CI. Manual backportTo create the backport manually run: Questions ?Please refer to the Backport tool documentation |
# Backport This will backport the following commits from `main` to `9.4`: - [Gracefully handle deprecated telemetry config (#266029)](#266029) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Eyo O. Eyo","email":"7893459+eokoneyo@users.noreply.github.com"},"sourceCommit":{"committedDate":"2026-04-28T16:07:25Z","message":"Gracefully handle deprecated telemetry config (#266029)\n\n## Summary\n\nInformed from [internal slack\nthread](https://elastic.slack.com/archives/C0D8P2XK5/p1777023957119899)\n\n`telemetry.enabled` is a deprecated config key. Its intended migration\npath is to translate a value of `false` into `telemetry.optIn: false` +\n`telemetry.allowChangingOptInStatus: false` and then remove the key, so\nthat the telemetry plugin itself continues to load while honoring the\nuser's intent to opt out. This allows dependent plugins — including\n`security_solution`, `fleet`, and others that declare `telemetry` as a\n`requiredPlugin` — to continue functioning normally.\n\n## The bug\n\nThe deprecation handler was checking for the disabled case with strict\nequality:\n\n```ts\nif (cfg.telemetry?.enabled === false) { ... }\n```\n\nThis did not account for the string `\"false\"`, which is a valid YAML\nvalue and one that `@kbn/config-schema`'s `schema.boolean()` type\nexplicitly coerces to the boolean `false`. The two systems run at\ndifferent moments in the startup pipeline:\n\n1. **Deprecations run first**, against the raw, pre-schema config object\ncoming directly from `kibana.yml`. At this point `\"false\"` is still a\nstring, so `\"false\" === false` evaluates to `false` and the migration is\nsilently skipped.\n2. **Schema validation runs second**, inside\n`ConfigService.isEnabledAtPath`. Here `schema.boolean()` coerces the\nstring `\"false\"` to the boolean `false`, causing `isEnabledAtPath` to\nreturn `false` and mark the plugin as disabled.\n\nBecause the plugin is disabled, every plugin that lists `telemetry` in\nits `requiredPlugins` is also transitively disabled — including\n`security_solution`, making it completely non-functional with no obvious\nerror pointing to the root cause.\n\n## The fix\n\nThe deprecation handler is updated to match any value that\n`schema.boolean()` would coerce to `false` — both the native boolean and\nany case-insensitive string variant — before schema validation has a\nchance to run, this ensures the migration fires regardless of how the\nvalue is expressed in `kibana.yml` (`false`, `\"false\"`, `\"False\"`,\n`\"FALSE\"`), removes `telemetry.enabled` from the config before\n`isEnabledAtPath` inspects it, and applies the correct opt-out semantics\nvia `optIn` and `allowChangingOptInStatus`. The OpenTelemetry\nsub-configs (`tracing.enabled`, `metrics.enabled`) are also set to\n`false` for consistency.\n\n## Tests\n\nA new `deprecations: telemetry.enabled` suite is added to\n`config.test.ts`. It drives the deprecation function directly through\n`applyDeprecations` (the same code path core uses at startup), and\nasserts:\n\n- All four falsy variants (`false`, `\"false\"`, `\"False\"`, `\"FALSE\"`)\ntrigger the migration, unset `enabled`, and correctly populate `optIn`,\n`allowChangingOptInStatus`, `tracing.enabled`, and `metrics.enabled`.\n- Absent or truthy values (`undefined`, `true`, `\"true\"`, `\"True\"`,\n`\"TRUE\"`) leave the config unchanged.\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"6f3c8892b7bbc83cc9b4bd0f4eda8b3f4ea536eb","branchLabelMapping":{"^v9.5.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Core","release_note:skip","backport:all-open","v9.5.0"],"title":"Gracefully handle deprecated telemetry config","number":266029,"url":"https://github.com/elastic/kibana/pull/266029","mergeCommit":{"message":"Gracefully handle deprecated telemetry config (#266029)\n\n## Summary\n\nInformed from [internal slack\nthread](https://elastic.slack.com/archives/C0D8P2XK5/p1777023957119899)\n\n`telemetry.enabled` is a deprecated config key. Its intended migration\npath is to translate a value of `false` into `telemetry.optIn: false` +\n`telemetry.allowChangingOptInStatus: false` and then remove the key, so\nthat the telemetry plugin itself continues to load while honoring the\nuser's intent to opt out. This allows dependent plugins — including\n`security_solution`, `fleet`, and others that declare `telemetry` as a\n`requiredPlugin` — to continue functioning normally.\n\n## The bug\n\nThe deprecation handler was checking for the disabled case with strict\nequality:\n\n```ts\nif (cfg.telemetry?.enabled === false) { ... }\n```\n\nThis did not account for the string `\"false\"`, which is a valid YAML\nvalue and one that `@kbn/config-schema`'s `schema.boolean()` type\nexplicitly coerces to the boolean `false`. The two systems run at\ndifferent moments in the startup pipeline:\n\n1. **Deprecations run first**, against the raw, pre-schema config object\ncoming directly from `kibana.yml`. At this point `\"false\"` is still a\nstring, so `\"false\" === false` evaluates to `false` and the migration is\nsilently skipped.\n2. **Schema validation runs second**, inside\n`ConfigService.isEnabledAtPath`. Here `schema.boolean()` coerces the\nstring `\"false\"` to the boolean `false`, causing `isEnabledAtPath` to\nreturn `false` and mark the plugin as disabled.\n\nBecause the plugin is disabled, every plugin that lists `telemetry` in\nits `requiredPlugins` is also transitively disabled — including\n`security_solution`, making it completely non-functional with no obvious\nerror pointing to the root cause.\n\n## The fix\n\nThe deprecation handler is updated to match any value that\n`schema.boolean()` would coerce to `false` — both the native boolean and\nany case-insensitive string variant — before schema validation has a\nchance to run, this ensures the migration fires regardless of how the\nvalue is expressed in `kibana.yml` (`false`, `\"false\"`, `\"False\"`,\n`\"FALSE\"`), removes `telemetry.enabled` from the config before\n`isEnabledAtPath` inspects it, and applies the correct opt-out semantics\nvia `optIn` and `allowChangingOptInStatus`. The OpenTelemetry\nsub-configs (`tracing.enabled`, `metrics.enabled`) are also set to\n`false` for consistency.\n\n## Tests\n\nA new `deprecations: telemetry.enabled` suite is added to\n`config.test.ts`. It drives the deprecation function directly through\n`applyDeprecations` (the same code path core uses at startup), and\nasserts:\n\n- All four falsy variants (`false`, `\"false\"`, `\"False\"`, `\"FALSE\"`)\ntrigger the migration, unset `enabled`, and correctly populate `optIn`,\n`allowChangingOptInStatus`, `tracing.enabled`, and `metrics.enabled`.\n- Absent or truthy values (`undefined`, `true`, `\"true\"`, `\"True\"`,\n`\"TRUE\"`) leave the config unchanged.\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"6f3c8892b7bbc83cc9b4bd0f4eda8b3f4ea536eb"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.5.0","branchLabelMappingKey":"^v9.5.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/266029","number":266029,"mergeCommit":{"message":"Gracefully handle deprecated telemetry config (#266029)\n\n## Summary\n\nInformed from [internal slack\nthread](https://elastic.slack.com/archives/C0D8P2XK5/p1777023957119899)\n\n`telemetry.enabled` is a deprecated config key. Its intended migration\npath is to translate a value of `false` into `telemetry.optIn: false` +\n`telemetry.allowChangingOptInStatus: false` and then remove the key, so\nthat the telemetry plugin itself continues to load while honoring the\nuser's intent to opt out. This allows dependent plugins — including\n`security_solution`, `fleet`, and others that declare `telemetry` as a\n`requiredPlugin` — to continue functioning normally.\n\n## The bug\n\nThe deprecation handler was checking for the disabled case with strict\nequality:\n\n```ts\nif (cfg.telemetry?.enabled === false) { ... }\n```\n\nThis did not account for the string `\"false\"`, which is a valid YAML\nvalue and one that `@kbn/config-schema`'s `schema.boolean()` type\nexplicitly coerces to the boolean `false`. The two systems run at\ndifferent moments in the startup pipeline:\n\n1. **Deprecations run first**, against the raw, pre-schema config object\ncoming directly from `kibana.yml`. At this point `\"false\"` is still a\nstring, so `\"false\" === false` evaluates to `false` and the migration is\nsilently skipped.\n2. **Schema validation runs second**, inside\n`ConfigService.isEnabledAtPath`. Here `schema.boolean()` coerces the\nstring `\"false\"` to the boolean `false`, causing `isEnabledAtPath` to\nreturn `false` and mark the plugin as disabled.\n\nBecause the plugin is disabled, every plugin that lists `telemetry` in\nits `requiredPlugins` is also transitively disabled — including\n`security_solution`, making it completely non-functional with no obvious\nerror pointing to the root cause.\n\n## The fix\n\nThe deprecation handler is updated to match any value that\n`schema.boolean()` would coerce to `false` — both the native boolean and\nany case-insensitive string variant — before schema validation has a\nchance to run, this ensures the migration fires regardless of how the\nvalue is expressed in `kibana.yml` (`false`, `\"false\"`, `\"False\"`,\n`\"FALSE\"`), removes `telemetry.enabled` from the config before\n`isEnabledAtPath` inspects it, and applies the correct opt-out semantics\nvia `optIn` and `allowChangingOptInStatus`. The OpenTelemetry\nsub-configs (`tracing.enabled`, `metrics.enabled`) are also set to\n`false` for consistency.\n\n## Tests\n\nA new `deprecations: telemetry.enabled` suite is added to\n`config.test.ts`. It drives the deprecation function directly through\n`applyDeprecations` (the same code path core uses at startup), and\nasserts:\n\n- All four falsy variants (`false`, `\"false\"`, `\"False\"`, `\"FALSE\"`)\ntrigger the migration, unset `enabled`, and correctly populate `optIn`,\n`allowChangingOptInStatus`, `tracing.enabled`, and `metrics.enabled`.\n- Absent or truthy values (`undefined`, `true`, `\"true\"`, `\"True\"`,\n`\"TRUE\"`) leave the config unchanged.\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"6f3c8892b7bbc83cc9b4bd0f4eda8b3f4ea536eb"}}]}] BACKPORT--> Co-authored-by: Eyo O. Eyo <7893459+eokoneyo@users.noreply.github.com>
# Backport This will backport the following commits from `main` to `9.3`: - [Gracefully handle deprecated telemetry config (#266029)](#266029) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Eyo O. Eyo","email":"7893459+eokoneyo@users.noreply.github.com"},"sourceCommit":{"committedDate":"2026-04-28T16:07:25Z","message":"Gracefully handle deprecated telemetry config (#266029)\n\n## Summary\n\nInformed from [internal slack\nthread](https://elastic.slack.com/archives/C0D8P2XK5/p1777023957119899)\n\n`telemetry.enabled` is a deprecated config key. Its intended migration\npath is to translate a value of `false` into `telemetry.optIn: false` +\n`telemetry.allowChangingOptInStatus: false` and then remove the key, so\nthat the telemetry plugin itself continues to load while honoring the\nuser's intent to opt out. This allows dependent plugins — including\n`security_solution`, `fleet`, and others that declare `telemetry` as a\n`requiredPlugin` — to continue functioning normally.\n\n## The bug\n\nThe deprecation handler was checking for the disabled case with strict\nequality:\n\n```ts\nif (cfg.telemetry?.enabled === false) { ... }\n```\n\nThis did not account for the string `\"false\"`, which is a valid YAML\nvalue and one that `@kbn/config-schema`'s `schema.boolean()` type\nexplicitly coerces to the boolean `false`. The two systems run at\ndifferent moments in the startup pipeline:\n\n1. **Deprecations run first**, against the raw, pre-schema config object\ncoming directly from `kibana.yml`. At this point `\"false\"` is still a\nstring, so `\"false\" === false` evaluates to `false` and the migration is\nsilently skipped.\n2. **Schema validation runs second**, inside\n`ConfigService.isEnabledAtPath`. Here `schema.boolean()` coerces the\nstring `\"false\"` to the boolean `false`, causing `isEnabledAtPath` to\nreturn `false` and mark the plugin as disabled.\n\nBecause the plugin is disabled, every plugin that lists `telemetry` in\nits `requiredPlugins` is also transitively disabled — including\n`security_solution`, making it completely non-functional with no obvious\nerror pointing to the root cause.\n\n## The fix\n\nThe deprecation handler is updated to match any value that\n`schema.boolean()` would coerce to `false` — both the native boolean and\nany case-insensitive string variant — before schema validation has a\nchance to run, this ensures the migration fires regardless of how the\nvalue is expressed in `kibana.yml` (`false`, `\"false\"`, `\"False\"`,\n`\"FALSE\"`), removes `telemetry.enabled` from the config before\n`isEnabledAtPath` inspects it, and applies the correct opt-out semantics\nvia `optIn` and `allowChangingOptInStatus`. The OpenTelemetry\nsub-configs (`tracing.enabled`, `metrics.enabled`) are also set to\n`false` for consistency.\n\n## Tests\n\nA new `deprecations: telemetry.enabled` suite is added to\n`config.test.ts`. It drives the deprecation function directly through\n`applyDeprecations` (the same code path core uses at startup), and\nasserts:\n\n- All four falsy variants (`false`, `\"false\"`, `\"False\"`, `\"FALSE\"`)\ntrigger the migration, unset `enabled`, and correctly populate `optIn`,\n`allowChangingOptInStatus`, `tracing.enabled`, and `metrics.enabled`.\n- Absent or truthy values (`undefined`, `true`, `\"true\"`, `\"True\"`,\n`\"TRUE\"`) leave the config unchanged.\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"6f3c8892b7bbc83cc9b4bd0f4eda8b3f4ea536eb","branchLabelMapping":{"^v9.5.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Core","release_note:skip","backport:all-open","v9.5.0"],"title":"Gracefully handle deprecated telemetry config","number":266029,"url":"https://github.com/elastic/kibana/pull/266029","mergeCommit":{"message":"Gracefully handle deprecated telemetry config (#266029)\n\n## Summary\n\nInformed from [internal slack\nthread](https://elastic.slack.com/archives/C0D8P2XK5/p1777023957119899)\n\n`telemetry.enabled` is a deprecated config key. Its intended migration\npath is to translate a value of `false` into `telemetry.optIn: false` +\n`telemetry.allowChangingOptInStatus: false` and then remove the key, so\nthat the telemetry plugin itself continues to load while honoring the\nuser's intent to opt out. This allows dependent plugins — including\n`security_solution`, `fleet`, and others that declare `telemetry` as a\n`requiredPlugin` — to continue functioning normally.\n\n## The bug\n\nThe deprecation handler was checking for the disabled case with strict\nequality:\n\n```ts\nif (cfg.telemetry?.enabled === false) { ... }\n```\n\nThis did not account for the string `\"false\"`, which is a valid YAML\nvalue and one that `@kbn/config-schema`'s `schema.boolean()` type\nexplicitly coerces to the boolean `false`. The two systems run at\ndifferent moments in the startup pipeline:\n\n1. **Deprecations run first**, against the raw, pre-schema config object\ncoming directly from `kibana.yml`. At this point `\"false\"` is still a\nstring, so `\"false\" === false` evaluates to `false` and the migration is\nsilently skipped.\n2. **Schema validation runs second**, inside\n`ConfigService.isEnabledAtPath`. Here `schema.boolean()` coerces the\nstring `\"false\"` to the boolean `false`, causing `isEnabledAtPath` to\nreturn `false` and mark the plugin as disabled.\n\nBecause the plugin is disabled, every plugin that lists `telemetry` in\nits `requiredPlugins` is also transitively disabled — including\n`security_solution`, making it completely non-functional with no obvious\nerror pointing to the root cause.\n\n## The fix\n\nThe deprecation handler is updated to match any value that\n`schema.boolean()` would coerce to `false` — both the native boolean and\nany case-insensitive string variant — before schema validation has a\nchance to run, this ensures the migration fires regardless of how the\nvalue is expressed in `kibana.yml` (`false`, `\"false\"`, `\"False\"`,\n`\"FALSE\"`), removes `telemetry.enabled` from the config before\n`isEnabledAtPath` inspects it, and applies the correct opt-out semantics\nvia `optIn` and `allowChangingOptInStatus`. The OpenTelemetry\nsub-configs (`tracing.enabled`, `metrics.enabled`) are also set to\n`false` for consistency.\n\n## Tests\n\nA new `deprecations: telemetry.enabled` suite is added to\n`config.test.ts`. It drives the deprecation function directly through\n`applyDeprecations` (the same code path core uses at startup), and\nasserts:\n\n- All four falsy variants (`false`, `\"false\"`, `\"False\"`, `\"FALSE\"`)\ntrigger the migration, unset `enabled`, and correctly populate `optIn`,\n`allowChangingOptInStatus`, `tracing.enabled`, and `metrics.enabled`.\n- Absent or truthy values (`undefined`, `true`, `\"true\"`, `\"True\"`,\n`\"TRUE\"`) leave the config unchanged.\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"6f3c8892b7bbc83cc9b4bd0f4eda8b3f4ea536eb"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.5.0","branchLabelMappingKey":"^v9.5.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/266029","number":266029,"mergeCommit":{"message":"Gracefully handle deprecated telemetry config (#266029)\n\n## Summary\n\nInformed from [internal slack\nthread](https://elastic.slack.com/archives/C0D8P2XK5/p1777023957119899)\n\n`telemetry.enabled` is a deprecated config key. Its intended migration\npath is to translate a value of `false` into `telemetry.optIn: false` +\n`telemetry.allowChangingOptInStatus: false` and then remove the key, so\nthat the telemetry plugin itself continues to load while honoring the\nuser's intent to opt out. This allows dependent plugins — including\n`security_solution`, `fleet`, and others that declare `telemetry` as a\n`requiredPlugin` — to continue functioning normally.\n\n## The bug\n\nThe deprecation handler was checking for the disabled case with strict\nequality:\n\n```ts\nif (cfg.telemetry?.enabled === false) { ... }\n```\n\nThis did not account for the string `\"false\"`, which is a valid YAML\nvalue and one that `@kbn/config-schema`'s `schema.boolean()` type\nexplicitly coerces to the boolean `false`. The two systems run at\ndifferent moments in the startup pipeline:\n\n1. **Deprecations run first**, against the raw, pre-schema config object\ncoming directly from `kibana.yml`. At this point `\"false\"` is still a\nstring, so `\"false\" === false` evaluates to `false` and the migration is\nsilently skipped.\n2. **Schema validation runs second**, inside\n`ConfigService.isEnabledAtPath`. Here `schema.boolean()` coerces the\nstring `\"false\"` to the boolean `false`, causing `isEnabledAtPath` to\nreturn `false` and mark the plugin as disabled.\n\nBecause the plugin is disabled, every plugin that lists `telemetry` in\nits `requiredPlugins` is also transitively disabled — including\n`security_solution`, making it completely non-functional with no obvious\nerror pointing to the root cause.\n\n## The fix\n\nThe deprecation handler is updated to match any value that\n`schema.boolean()` would coerce to `false` — both the native boolean and\nany case-insensitive string variant — before schema validation has a\nchance to run, this ensures the migration fires regardless of how the\nvalue is expressed in `kibana.yml` (`false`, `\"false\"`, `\"False\"`,\n`\"FALSE\"`), removes `telemetry.enabled` from the config before\n`isEnabledAtPath` inspects it, and applies the correct opt-out semantics\nvia `optIn` and `allowChangingOptInStatus`. The OpenTelemetry\nsub-configs (`tracing.enabled`, `metrics.enabled`) are also set to\n`false` for consistency.\n\n## Tests\n\nA new `deprecations: telemetry.enabled` suite is added to\n`config.test.ts`. It drives the deprecation function directly through\n`applyDeprecations` (the same code path core uses at startup), and\nasserts:\n\n- All four falsy variants (`false`, `\"false\"`, `\"False\"`, `\"FALSE\"`)\ntrigger the migration, unset `enabled`, and correctly populate `optIn`,\n`allowChangingOptInStatus`, `tracing.enabled`, and `metrics.enabled`.\n- Absent or truthy values (`undefined`, `true`, `\"true\"`, `\"True\"`,\n`\"TRUE\"`) leave the config unchanged.\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"6f3c8892b7bbc83cc9b4bd0f4eda8b3f4ea536eb"}}]}] BACKPORT--> Co-authored-by: Eyo O. Eyo <7893459+eokoneyo@users.noreply.github.com>
# Backport This will backport the following commits from `main` to `9.2`: - [Gracefully handle deprecated telemetry config (#266029)](#266029) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Eyo O. Eyo","email":"7893459+eokoneyo@users.noreply.github.com"},"sourceCommit":{"committedDate":"2026-04-28T16:07:25Z","message":"Gracefully handle deprecated telemetry config (#266029)\n\n## Summary\n\nInformed from [internal slack\nthread](https://elastic.slack.com/archives/C0D8P2XK5/p1777023957119899)\n\n`telemetry.enabled` is a deprecated config key. Its intended migration\npath is to translate a value of `false` into `telemetry.optIn: false` +\n`telemetry.allowChangingOptInStatus: false` and then remove the key, so\nthat the telemetry plugin itself continues to load while honoring the\nuser's intent to opt out. This allows dependent plugins — including\n`security_solution`, `fleet`, and others that declare `telemetry` as a\n`requiredPlugin` — to continue functioning normally.\n\n## The bug\n\nThe deprecation handler was checking for the disabled case with strict\nequality:\n\n```ts\nif (cfg.telemetry?.enabled === false) { ... }\n```\n\nThis did not account for the string `\"false\"`, which is a valid YAML\nvalue and one that `@kbn/config-schema`'s `schema.boolean()` type\nexplicitly coerces to the boolean `false`. The two systems run at\ndifferent moments in the startup pipeline:\n\n1. **Deprecations run first**, against the raw, pre-schema config object\ncoming directly from `kibana.yml`. At this point `\"false\"` is still a\nstring, so `\"false\" === false` evaluates to `false` and the migration is\nsilently skipped.\n2. **Schema validation runs second**, inside\n`ConfigService.isEnabledAtPath`. Here `schema.boolean()` coerces the\nstring `\"false\"` to the boolean `false`, causing `isEnabledAtPath` to\nreturn `false` and mark the plugin as disabled.\n\nBecause the plugin is disabled, every plugin that lists `telemetry` in\nits `requiredPlugins` is also transitively disabled — including\n`security_solution`, making it completely non-functional with no obvious\nerror pointing to the root cause.\n\n## The fix\n\nThe deprecation handler is updated to match any value that\n`schema.boolean()` would coerce to `false` — both the native boolean and\nany case-insensitive string variant — before schema validation has a\nchance to run, this ensures the migration fires regardless of how the\nvalue is expressed in `kibana.yml` (`false`, `\"false\"`, `\"False\"`,\n`\"FALSE\"`), removes `telemetry.enabled` from the config before\n`isEnabledAtPath` inspects it, and applies the correct opt-out semantics\nvia `optIn` and `allowChangingOptInStatus`. The OpenTelemetry\nsub-configs (`tracing.enabled`, `metrics.enabled`) are also set to\n`false` for consistency.\n\n## Tests\n\nA new `deprecations: telemetry.enabled` suite is added to\n`config.test.ts`. It drives the deprecation function directly through\n`applyDeprecations` (the same code path core uses at startup), and\nasserts:\n\n- All four falsy variants (`false`, `\"false\"`, `\"False\"`, `\"FALSE\"`)\ntrigger the migration, unset `enabled`, and correctly populate `optIn`,\n`allowChangingOptInStatus`, `tracing.enabled`, and `metrics.enabled`.\n- Absent or truthy values (`undefined`, `true`, `\"true\"`, `\"True\"`,\n`\"TRUE\"`) leave the config unchanged.\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"6f3c8892b7bbc83cc9b4bd0f4eda8b3f4ea536eb","branchLabelMapping":{"^v9.5.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Core","release_note:skip","backport:all-open","v9.5.0"],"title":"Gracefully handle deprecated telemetry config","number":266029,"url":"https://github.com/elastic/kibana/pull/266029","mergeCommit":{"message":"Gracefully handle deprecated telemetry config (#266029)\n\n## Summary\n\nInformed from [internal slack\nthread](https://elastic.slack.com/archives/C0D8P2XK5/p1777023957119899)\n\n`telemetry.enabled` is a deprecated config key. Its intended migration\npath is to translate a value of `false` into `telemetry.optIn: false` +\n`telemetry.allowChangingOptInStatus: false` and then remove the key, so\nthat the telemetry plugin itself continues to load while honoring the\nuser's intent to opt out. This allows dependent plugins — including\n`security_solution`, `fleet`, and others that declare `telemetry` as a\n`requiredPlugin` — to continue functioning normally.\n\n## The bug\n\nThe deprecation handler was checking for the disabled case with strict\nequality:\n\n```ts\nif (cfg.telemetry?.enabled === false) { ... }\n```\n\nThis did not account for the string `\"false\"`, which is a valid YAML\nvalue and one that `@kbn/config-schema`'s `schema.boolean()` type\nexplicitly coerces to the boolean `false`. The two systems run at\ndifferent moments in the startup pipeline:\n\n1. **Deprecations run first**, against the raw, pre-schema config object\ncoming directly from `kibana.yml`. At this point `\"false\"` is still a\nstring, so `\"false\" === false` evaluates to `false` and the migration is\nsilently skipped.\n2. **Schema validation runs second**, inside\n`ConfigService.isEnabledAtPath`. Here `schema.boolean()` coerces the\nstring `\"false\"` to the boolean `false`, causing `isEnabledAtPath` to\nreturn `false` and mark the plugin as disabled.\n\nBecause the plugin is disabled, every plugin that lists `telemetry` in\nits `requiredPlugins` is also transitively disabled — including\n`security_solution`, making it completely non-functional with no obvious\nerror pointing to the root cause.\n\n## The fix\n\nThe deprecation handler is updated to match any value that\n`schema.boolean()` would coerce to `false` — both the native boolean and\nany case-insensitive string variant — before schema validation has a\nchance to run, this ensures the migration fires regardless of how the\nvalue is expressed in `kibana.yml` (`false`, `\"false\"`, `\"False\"`,\n`\"FALSE\"`), removes `telemetry.enabled` from the config before\n`isEnabledAtPath` inspects it, and applies the correct opt-out semantics\nvia `optIn` and `allowChangingOptInStatus`. The OpenTelemetry\nsub-configs (`tracing.enabled`, `metrics.enabled`) are also set to\n`false` for consistency.\n\n## Tests\n\nA new `deprecations: telemetry.enabled` suite is added to\n`config.test.ts`. It drives the deprecation function directly through\n`applyDeprecations` (the same code path core uses at startup), and\nasserts:\n\n- All four falsy variants (`false`, `\"false\"`, `\"False\"`, `\"FALSE\"`)\ntrigger the migration, unset `enabled`, and correctly populate `optIn`,\n`allowChangingOptInStatus`, `tracing.enabled`, and `metrics.enabled`.\n- Absent or truthy values (`undefined`, `true`, `\"true\"`, `\"True\"`,\n`\"TRUE\"`) leave the config unchanged.\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"6f3c8892b7bbc83cc9b4bd0f4eda8b3f4ea536eb"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.5.0","branchLabelMappingKey":"^v9.5.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/266029","number":266029,"mergeCommit":{"message":"Gracefully handle deprecated telemetry config (#266029)\n\n## Summary\n\nInformed from [internal slack\nthread](https://elastic.slack.com/archives/C0D8P2XK5/p1777023957119899)\n\n`telemetry.enabled` is a deprecated config key. Its intended migration\npath is to translate a value of `false` into `telemetry.optIn: false` +\n`telemetry.allowChangingOptInStatus: false` and then remove the key, so\nthat the telemetry plugin itself continues to load while honoring the\nuser's intent to opt out. This allows dependent plugins — including\n`security_solution`, `fleet`, and others that declare `telemetry` as a\n`requiredPlugin` — to continue functioning normally.\n\n## The bug\n\nThe deprecation handler was checking for the disabled case with strict\nequality:\n\n```ts\nif (cfg.telemetry?.enabled === false) { ... }\n```\n\nThis did not account for the string `\"false\"`, which is a valid YAML\nvalue and one that `@kbn/config-schema`'s `schema.boolean()` type\nexplicitly coerces to the boolean `false`. The two systems run at\ndifferent moments in the startup pipeline:\n\n1. **Deprecations run first**, against the raw, pre-schema config object\ncoming directly from `kibana.yml`. At this point `\"false\"` is still a\nstring, so `\"false\" === false` evaluates to `false` and the migration is\nsilently skipped.\n2. **Schema validation runs second**, inside\n`ConfigService.isEnabledAtPath`. Here `schema.boolean()` coerces the\nstring `\"false\"` to the boolean `false`, causing `isEnabledAtPath` to\nreturn `false` and mark the plugin as disabled.\n\nBecause the plugin is disabled, every plugin that lists `telemetry` in\nits `requiredPlugins` is also transitively disabled — including\n`security_solution`, making it completely non-functional with no obvious\nerror pointing to the root cause.\n\n## The fix\n\nThe deprecation handler is updated to match any value that\n`schema.boolean()` would coerce to `false` — both the native boolean and\nany case-insensitive string variant — before schema validation has a\nchance to run, this ensures the migration fires regardless of how the\nvalue is expressed in `kibana.yml` (`false`, `\"false\"`, `\"False\"`,\n`\"FALSE\"`), removes `telemetry.enabled` from the config before\n`isEnabledAtPath` inspects it, and applies the correct opt-out semantics\nvia `optIn` and `allowChangingOptInStatus`. The OpenTelemetry\nsub-configs (`tracing.enabled`, `metrics.enabled`) are also set to\n`false` for consistency.\n\n## Tests\n\nA new `deprecations: telemetry.enabled` suite is added to\n`config.test.ts`. It drives the deprecation function directly through\n`applyDeprecations` (the same code path core uses at startup), and\nasserts:\n\n- All four falsy variants (`false`, `\"false\"`, `\"False\"`, `\"FALSE\"`)\ntrigger the migration, unset `enabled`, and correctly populate `optIn`,\n`allowChangingOptInStatus`, `tracing.enabled`, and `metrics.enabled`.\n- Absent or truthy values (`undefined`, `true`, `\"true\"`, `\"True\"`,\n`\"TRUE\"`) leave the config unchanged.\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"6f3c8892b7bbc83cc9b4bd0f4eda8b3f4ea536eb"}}]}] BACKPORT--> Co-authored-by: Eyo O. Eyo <7893459+eokoneyo@users.noreply.github.com>
💔 Some backports could not be created
Note: Successful backport PRs will be merged automatically after passing CI. Manual backportTo create the backport manually run: Questions ?Please refer to the Backport tool documentation |
|
versions |
Summary
Informed from internal slack thread
telemetry.enabledis a deprecated config key. Its intended migration path is to translate a value offalseintotelemetry.optIn: false+telemetry.allowChangingOptInStatus: falseand then remove the key, so that the telemetry plugin itself continues to load while honoring the user's intent to opt out. This allows dependent plugins — includingsecurity_solution,fleet, and others that declaretelemetryas arequiredPlugin— to continue functioning normally.The bug
The deprecation handler was checking for the disabled case with strict equality:
This did not account for the string
"false", which is a valid YAML value and one that@kbn/config-schema'sschema.boolean()type explicitly coerces to the booleanfalse. The two systems run at different moments in the startup pipeline:kibana.yml. At this point"false"is still a string, so"false" === falseevaluates tofalseand the migration is silently skipped.ConfigService.isEnabledAtPath. Hereschema.boolean()coerces the string"false"to the booleanfalse, causingisEnabledAtPathto returnfalseand mark the plugin as disabled.Because the plugin is disabled, every plugin that lists
telemetryin itsrequiredPluginsis also transitively disabled — includingsecurity_solution, making it completely non-functional with no obvious error pointing to the root cause.The fix
The deprecation handler is updated to match any value that
schema.boolean()would coerce tofalse— both the native boolean and any case-insensitive string variant — before schema validation has a chance to run, this ensures the migration fires regardless of how the value is expressed inkibana.yml(false,"false","False","FALSE"), removestelemetry.enabledfrom the config beforeisEnabledAtPathinspects it, and applies the correct opt-out semantics viaoptInandallowChangingOptInStatus. The OpenTelemetry sub-configs (tracing.enabled,metrics.enabled) are also set tofalsefor consistency.Tests
A new
deprecations: telemetry.enabledsuite is added toconfig.test.ts. It drives the deprecation function directly throughapplyDeprecations(the same code path core uses at startup), and asserts:false,"false","False","FALSE") trigger the migration, unsetenabled, and correctly populateoptIn,allowChangingOptInStatus,tracing.enabled, andmetrics.enabled.undefined,true,"true","True","TRUE") leave the config unchanged.