Skip to content

Added the OpenTelemetry packages as direct dependencies, as `@sentry/… - #355

Merged
GermanBluefox merged 2 commits into
masterfrom
fixing-missing-deps
Sep 16, 2026
Merged

GermanBluefox merged 2 commits into
masterfrom
fixing-missing-deps

Conversation

@GermanBluefox

@GermanBluefox GermanBluefox commented Sep 16, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Users report this error in the log, typically right after an adapter update:

error: cloud.1 (9136) Plugin sentry Failed to initialize plugin: Cannot find package '@opentelemetry/instrumentation' imported from /opt/iobroker/node_modules/@sentry/node-core/build/esm/otel/instrument.js

The adapter itself keeps running — only the error reporting is dead — but the message looks alarming and gets reported as an adapter bug.

Root cause

@sentry/node-core imports several OpenTelemetry packages at runtime, but declares all of them as optional peer dependencies:

"peerDependenciesMeta": {
    "@opentelemetry/api":                      { "optional": true },
    "@opentelemetry/core":                     { "optional": true },
    "@opentelemetry/instrumentation":          { "optional": true },
    "@opentelemetry/sdk-trace-base":           { "optional": true },
    "@opentelemetry/exporter-trace-otlp-http": { "optional": true }
}

Because they are optional, npm never installs them on behalf of node-core. They only end up in the tree at all because @sentry/node happens to list three of them as direct dependencies.

All ioBroker adapters share one flat /opt/iobroker/node_modules. @sentry/node-core is hoisted to the top level there, so it can only resolve @opentelemetry/instrumentation from that same top level. As soon as npm nests the OpenTelemetry packages under node_modules/@sentry/node/node_modules/ — which happens when something else in the flat tree claims a conflicting @opentelemetry/instrumentation version — the hoisted @sentry/node-core can no longer see them, and the dynamic import('@sentry/node') fails with the error above.

Changes

1. OpenTelemetry packages added as direct dependencies

So that npm is required to keep a satisfying copy next to the hoisted @sentry/node-core:

"@opentelemetry/api": "^1.9.1",
"@opentelemetry/core": "^1.30.1 || ^2.1.0",
"@opentelemetry/instrumentation": ">=0.57.1 <1",
"@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0"

The ranges are deliberately the wide ones that @sentry/node-core itself declares in its peer dependencies, rather than the narrower ones from @sentry/node. This way the plugin never narrows the resolution, and future @sentry/node bumps (e.g. @opentelemetry/instrumentation 0.220 → 0.230) still dedupe to a single top-level copy instead of forcing a second, nested one — which would reintroduce exactly the bug being fixed here.

@opentelemetry/exporter-trace-otlp-http and @opentelemetry/context-async-hooks are intentionally left out: they are only referenced from lazily loaded OTLP exporter code paths that init() never reaches.

2. An incomplete installation no longer produces a cryptic resolution error

import('@sentry/node') moved into a new _loadSentry(), which catches ERR_MODULE_NOT_FOUND / MODULE_NOT_FOUND, extracts the name of the missing package and logs a readable, actionable warning. Every other error is re-thrown unchanged.

Before:

error: Plugin sentry Failed to initialize plugin: Cannot find package '@opentelemetry/instrumentation' imported from /opt/iobroker/node_modules/@sentry/node-core/build/esm/otel/instrument.js

After:

warn: Sentry Plugin cannot be loaded because the package "@opentelemetry/instrumentation" is not installed. This is an incomplete npm installation and does not influence the functionality of iobroker.cloud. To repair it, execute "npm install" in the ioBroker directory (normally /opt/iobroker).
error: Plugin sentry Failed to initialize plugin: Sentry Plugin disabled because it is not installed completely

The plugin still throws so that PluginBase deactivates it — but with a message that tells the user what actually happened.

3. Two related bugs fixed along the way

  • this.reallyEnabled = true was set before the import. If the import failed, the flag stayed true while this.Sentry remained undefined, so getSentryObject() would hand out undefined to adapters. It is now set only after the module has successfully loaded.
  • require('source-map-support') was unguarded and can fail with the same class of error. It is now wrapped in try/catch — without it, only the original source locations in stack traces are lost.

4. Dependency updates

@sentry/node → ^10.74.0, baseline-browser-mapping (dev) → ^2.11.24, lockfile regenerated.

Testing

Verified on this branch with a clean npm ci on Node.js 22.23.2:

  • npm run build and npm run lint pass, and the committed build/ output matches a fresh compile.
  • After npm ci, all four OpenTelemetry packages resolve at the top level of node_modules; there are no nested duplicates of @opentelemetry/* or @sentry/*.
  • _registerSentry() behaviour in three different trees:
Dependency tree Result
complete Sentry initialized, reallyEnabled = true
@opentelemetry/instrumentation removed warning as shown above, clean deactivation, reallyEnabled = false, Sentry stays undefined
@sentry/node removed warning correctly names @sentry/node, same clean deactivation

…node-core` declares them only as optional peer dependencies and npm does not necessarily install them
@GermanBluefox
GermanBluefox merged commit c18bc4a into master Sep 16, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants