Repository navigation
Plugin not sending traces: 3 root causes identified (missing dep, tracer timing, Bun OTEL compat) #7
Description
Summary
After deep debugging (source-level tracing through both OpenCode's plugin loader and the plugin's own code), I identified 3 bugs that prevent @langfuse/opencode-observability-plugin from sending traces to Langfuse.
All testing done with OpenCode v1.17.13 on macOS (Bun runtime), Langfuse v3.205.1 self-hosted.
Bug #1: Missing fast-check transitive dependency
File: Plugin's node_modules after Npm.add() installation
Root cause: effect@3.21.4 depends on fast-check (peer/optional), but OpenCode's Npm.add() uses @npmcli/arborist with ignoreScripts: true, which skips optional/peer dependencies.
Symptom: import() of the plugin module fails with:
Cannot find package 'fast-check' from '.../effect/dist/esm/FastCheck.js'
Fix: Add fast-check as an explicit dependency in package.json, or ensure it's installed:
npm install fast-check --prefix ~/.cache/opencode/packages/@langfuse/opencode-observability-plugin@latestBug #2: Tracer created before SDK starts
File: src/langfuse.ts → createLangfuseClient()
Root cause: trace.getTracer() is called before sdk.start(). At that point, no global TracerProvider is registered, so ProxyTracer._getDelegate() returns NoopTracer. All subsequent startSpan() calls produce no-op spans that never reach the processor.
// ❌ Current code
const traceState = {
tracer: trace.getTracer(tracerName, PLUGIN_VERSION), // ← BEFORE sdk.start()
...
};
const sdk = new NodeSDK({ spanProcessors: [...] });
yield* Effect.sync(() => sdk.start()); // ← AFTERFix: Create the tracer AFTER sdk.start():
const traceState = { tracer: null, ... };
const sdk = new NodeSDK({ spanProcessors: [...] });
yield* Effect.sync(() => sdk.start());
traceState.tracer = trace.getTracer(tracerName, PLUGIN_VERSION); // ← AFTER sdk.start()Bug #3: Bun runtime — NodeSDK.start() global provider registration not recognized
Root cause: Even with Bug #2 fixed, @opentelemetry/api's global trace.getTracer()returns aProxyTracerthat delegates to a no-op provider. This appears to be a Bun-specific issue whereNodeSDK.start()callstrace.setGlobalTracerProvider()but the global registry isn't properly shared between@opentelemetry/sdk-nodeand the separately-resolved@opentelemetry/apiin the plugin'snode_modules`.
Fix: Bypass the global API entirely. Use NodeTracerProvider directly with provider.getTracer():
// ❌ Before
import { NodeSDK } from "@opentelemetry/sdk-node";
const sdk = new NodeSDK({ spanProcessors: [...] });
sdk.start();
const tracer = trace.getTracer(name, version);
// ✅ After
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
const provider = new NodeTracerProvider({ spanProcessors: [...] });
provider.register();
const tracer = provider.getTracer(name, version);Verification
After all three fixes, traces appear correctly in Langfuse:
scope: opencode-langfuse-plugin v0.1.0
sessionId: ses_0c80adcb8ffe97...
environment: development
observations: 3
Related
- Issue No traces appear in Langfuse Cloud when using OpenCode plugin #6 (closed as "cache issue" but the root cause was these bugs)
- Tested on OpenCode v1.17.13, Bun runtime, macOS
Activity
bezbac commentedon Aug 7, 2026
The plugin is now building most dependencies and only outputting one final
index.jswhich should hopefully fix these issues. Please give the newly released v0.2.0 a try.You might need to update your OpenCode config to explicitly reference this version if you’ve already used v0.1.0.