OTEL: claude_code.plugin_loaded dropped on every session start — event logger not initialized yet (same pattern as #58439)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet for this specific event (related: #58439, same underlying pattern for a different event)
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code available via npm at time of testing (confirmed changelog through 2.1.219 contains no related fix)
What's Wrong?
Summary
claude_code.plugin_loaded is dropped on every session start, for every installed plugin, because it fires before the OTel event logger finishes initializing. This is the same underlying race reported in #58439 for hook_execution_start (closed stale, unfixed) — a different event, identical root cause and log signature. Filing separately since #58439 is closed/stale and this instance is on the native CLI (not the VS Code extension) and affects plugin-load attribution specifically, but the fix is almost certainly shared.
Environment
- Claude Code: 2.1.206 (native CLI, macOS)
- Deployment: enterprise/MDM-managed (
/Library/Application Support/ClaudeCode/managed-settings.jsonpresent, setsCLAUDE_CODE_ENABLE_TELEMETRY=1,OTEL_LOGS_EXPORTER=otlp,OTEL_EXPORTER_OTLP_ENDPOINT=https://api.honeycomb.io, and related OTLP env vars) - OS: macOS darwin 25.5.0 arm64
- 2 plugins installed via a git-subdir marketplace source (one with a bare
SKILL.mdmanifest understrict: falseinline mode, one — tested locally — with a real.claude-plugin/plugin.json); both exhibit the identical drop, confirming the manifest shape is irrelevant to this bug
Reproduction
rm -f /tmp/claude-debug.log
claude --debug-file /tmp/claude-debug.log --print "hi" >/dev/null 2>&1
grep -i "3P telemetry\|event logger" /tmp/claude-debug.log
Output (reproduced identically across 3 consecutive clean runs):
2026-07-24T19:18:43.746Z [DEBUG] [3P telemetry] Waiting for remote managed settings before telemetry init
2026-07-24T19:18:43.750Z [DEBUG] [3P telemetry] Remote managed settings loaded, initializing telemetry
2026-07-24T19:18:43.776Z [DEBUG] [3P telemetry] isTelemetryEnabled=true (CLAUDE_CODE_ENABLE_TELEMETRY=1)
2026-07-24T19:18:43.776Z [DEBUG] [3P telemetry] getOtlpReaders: types=[], interval=60000, protocol=undefined, endpoint=undefined
2026-07-24T19:18:43.776Z [DEBUG] [3P telemetry] getOtlpLogExporters: types=[], protocol=undefined, endpoint=undefined
2026-07-24T19:18:43.777Z [DEBUG] [3P telemetry] Created 0 log exporter(s)
2026-07-24T19:18:43.785Z [WARN] [3P telemetry] Event dropped (no event logger initialized): plugin_loaded
Cross-checked against the org's live Honeycomb backend (claude-code dataset — note: a separate dataset from the more commonly-referenced claude dataset, which does not carry this event at all): a query for plugin.name exists AND marketplace.name = <our marketplace> over the trailing 7 days returns zero results, consistent with the event being dropped client-side on every session rather than merely mis-attributed or delayed in export.
Root cause
- Telemetry init is gated on an async network fetch (
"Waiting for remote managed settings before telemetry init") before the event logger/exporters are constructed. - Plugin loading is synchronous local disk I/O (reading
installed_plugins.json+ each plugin's cached directory) and firesplugin_loadedimmediately per plugin, with no wait on telemetry readiness. - Local disk I/O reliably finishes before a network round-trip completes, so
plugin_loadedalways loses this race — this is not an intermittent race, it reproduced 3/3 in testing. - This is identical in shape to #58439's
hook_execution_startdrop (~37msgap there vs. plugin loading here), suggesting a general pattern: any event fired during CLI startup, before telemetry init resolves its network-dependent managed-settings fetch, is silently and permanently dropped.
What Should Happen?
plugin_loaded (and other startup-window events, per the #58439 pattern) should reach the configured exporter(s) rather than being silently dropped. Suggested fixes, in order of preference:
- Buffer + flush: queue events fired before the event logger exists, replay them once telemetry init completes. Lowest risk, doesn't change startup ordering or latency.
- Defer emission: hold plugin-load's
plugin_loadedcall until telemetry init resolves (only safe if this doesn't materially delay plugin availability). - Local-first telemetry init: don't gate event-logger construction on the remote managed-settings network fetch; initialize with current env/local settings synchronously, merge remote managed settings in asynchronously afterward.
A minimal stop-gap, if a full fix isn't feasible short-term: emit a dropped-event counter metric so consumers at least know events are being lost, rather than silent, unrecoverable data loss (also suggested in #58439).
Error Messages/Logs
See reproduction section above — [WARN] [3P telemetry] Event dropped (no event logger initialized): plugin_loaded, reproduced 3/3 via --debug-file.
Related
- #58439 — same root-cause pattern (
hook_execution_start), closed stale without a fix; this issue reproduces the identical pattern for a different event on native CLI (not VS Code extension) and confirms it's unrelated to plugin manifest shape (plugin.jsonvs. inlineSKILL.md+strict: false) - #67657 — a related but distinct telemetry-init-ordering bug (managed-settings
envblock arriving too late for the OTEL SDK)
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗