Skip to content

Gracefully handle deprecated telemetry config#266029

Merged
eokoneyo merged 3 commits intoelastic:mainfrom
eokoneyo:fix/resolve-issue-where-string-value-in-telemetry-disables-dependent-plugins
Apr 28, 2026
Merged

Gracefully handle deprecated telemetry config#266029
eokoneyo merged 3 commits intoelastic:mainfrom
eokoneyo:fix/resolve-issue-where-string-value-in-telemetry-disables-dependent-plugins

Conversation

@eokoneyo
Copy link
Copy Markdown
Contributor

@eokoneyo eokoneyo commented Apr 28, 2026

Summary

Informed from internal slack thread

telemetry.enabled is a deprecated config key. Its intended migration path is to translate a value of false into telemetry.optIn: false + telemetry.allowChangingOptInStatus: false and 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 — including security_solution, fleet, and others that declare telemetry as a requiredPlugin — to continue functioning normally.

The bug

The deprecation handler was checking for the disabled case with strict equality:

if (cfg.telemetry?.enabled === false) { ... }

This did not account for the string "false", which is a valid YAML value and one that @kbn/config-schema's schema.boolean() type explicitly coerces to the boolean false. The two systems run at different moments in the startup pipeline:

  1. Deprecations run first, against the raw, pre-schema config object coming directly from kibana.yml. At this point "false" is still a string, so "false" === false evaluates to false and the migration is silently skipped.
  2. Schema validation runs second, inside ConfigService.isEnabledAtPath. Here schema.boolean() coerces the string "false" to the boolean false, causing isEnabledAtPath to return false and mark the plugin as disabled.

Because the plugin is disabled, every plugin that lists telemetry in its requiredPlugins is also transitively disabled — including security_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 to false — 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 in kibana.yml (false, "false", "False", "FALSE"), removes telemetry.enabled from the config before isEnabledAtPath inspects it, and applies the correct opt-out semantics via optIn and allowChangingOptInStatus. The OpenTelemetry sub-configs (tracing.enabled, metrics.enabled) are also set to false for consistency.

Tests

A new deprecations: telemetry.enabled suite is added to config.test.ts. It drives the deprecation function directly through applyDeprecations (the same code path core uses at startup), and asserts:

  • All four falsy variants (false, "false", "False", "FALSE") trigger the migration, unset enabled, and correctly populate optIn, allowChangingOptInStatus, tracing.enabled, and metrics.enabled.
  • Absent or truthy values (undefined, true, "true", "True", "TRUE") leave the config unchanged.

@eokoneyo eokoneyo self-assigned this Apr 28, 2026
@eokoneyo eokoneyo added Team:Core Platform Core services: plugins, logging, config, saved objects, http, ES client, i18n, etc t// release_note:skip Skip the PR/issue when compiling release notes backport:all-open Backport to all branches that could still receive a release labels Apr 28, 2026
@eokoneyo
Copy link
Copy Markdown
Contributor Author

/ci

@eokoneyo
Copy link
Copy Markdown
Contributor Author

/ci

@kibanamachine
Copy link
Copy Markdown
Contributor

💚 Build Succeeded

Metrics [docs]

✅ unchanged

History

cc @eokoneyo

@MoritzAtManserv
Copy link
Copy Markdown

FYI: There was also a forum post on this issue a while back: Elastic Security is missing in kibana [9.0.2]

@eokoneyo eokoneyo marked this pull request as ready for review April 28, 2026 14:32
@eokoneyo eokoneyo requested a review from a team as a code owner April 28, 2026 14:32
@infra-vault-gh-plugin-prod
Copy link
Copy Markdown

Pinging @elastic/kibana-core (Team:Core)

@eokoneyo
Copy link
Copy Markdown
Contributor Author

FYI: There was also a forum post on this issue a while back: Elastic Security is missing in kibana [9.0.2]

Yes we are aware, this fix will be applied to all affected versions after it merges.

@eokoneyo eokoneyo requested a review from afharo April 28, 2026 15:52
@eokoneyo eokoneyo merged commit 6f3c889 into elastic:main Apr 28, 2026
22 checks passed
@eokoneyo eokoneyo deleted the fix/resolve-issue-where-string-value-in-telemetry-disables-dependent-plugins branch April 28, 2026 16:07
@kibanamachine
Copy link
Copy Markdown
Contributor

Starting backport for target branches: 8.19, 9.2, 9.3, 9.4

https://github.com/elastic/kibana/actions/runs/25064030767

@kibanamachine
Copy link
Copy Markdown
Contributor

💔 Some backports could not be created

Status Branch Result
8.19 Backport failed because of merge conflicts

You might need to backport the following PRs to 8.19:
- [CI] Jest through moon (#259075)
9.2
9.3
9.4

Note: Successful backport PRs will be merged automatically after passing CI.

Manual backport

To create the backport manually run:

node scripts/backport --pr 266029

Questions ?

Please refer to the Backport tool documentation

kibanamachine added a commit that referenced this pull request Apr 28, 2026
# 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>
kibanamachine added a commit that referenced this pull request Apr 28, 2026
# 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>
kibanamachine added a commit that referenced this pull request Apr 28, 2026
# 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>
@eokoneyo
Copy link
Copy Markdown
Contributor Author

💔 Some backports could not be created

Status Branch Result
9.1
9.0 Conflict resolution was aborted by the user

Note: Successful backport PRs will be merged automatically after passing CI.

Manual backport

To create the backport manually run:

node scripts/backport --pr 266029

Questions ?

Please refer to the Backport tool documentation

@eokoneyo
Copy link
Copy Markdown
Contributor Author

versions 9.0 & 9.1 aren't accepting backports, so customers that encounter this issue, use the false boolean value to configure telemetry.enabled in place of the string literal "false".

@Ikuni17 Ikuni17 added v9.3.5 and removed v9.3.4 labels May 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:all-open Backport to all branches that could still receive a release release_note:skip Skip the PR/issue when compiling release notes Team:Core Platform Core services: plugins, logging, config, saved objects, http, ES client, i18n, etc t// v9.2.9 v9.3.5 v9.4.0 v9.5.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants