quarkusio/quarkus · error · IllegalArgumentException

The Vert.x Context to attach the OpenTelemetry Context must

Error message

The Vert.x Context to attach the OpenTelemetry Context must be a duplicated Context

What it means

QuarkusContextStorage (the OpenTelemetry Context storage backed by Vert.x) only permits attaching an OpenTelemetry Context to a Vert.x Context that is a duplicated context (a child context forked per-request/operation). Attaching to a root/unduplicated context would leak traces across requests, so the storage throws IllegalArgumentException('The Vert.x Context to attach the OpenTelemetry Context must be a duplicated Context').

Source

Thrown at extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/QuarkusContextStorage.java:60

        return vertxContext != null && isDuplicatedContext(vertxContext) ? attach(vertxContext, otelToAttach)
                : FALLBACK_CONTEXT_STORAGE.attach(otelToAttach);
    }

    /**
     * Attach the OpenTelemetry Context in the Vert.x Context if it is a duplicated Vert.x Context.
     *
     * @param vertxContext the Vert.x Context to attach the OpenTelemetry Context
     * @param otelToAttach the OpenTelemetry Context to attach
     * @return the Scope of the OpenTelemetry Context
     */
    public Scope attach(io.vertx.core.Context vertxContext, Context otelToAttach) {
        if (vertxContext == null || otelToAttach == null) {
            return Scope.noop();
        }

        // We don't allow to attach the OpenTelemetry Context to a Vert.x Context that is not a duplicate.
        if (!isDuplicatedContext(vertxContext)) {
            throw new IllegalArgumentException(
                    "The Vert.x Context to attach the OpenTelemetry Context must be a duplicated Context");
        }

        Context otelBeforeAttach = getOtelContext(vertxContext);
        if (otelToAttach == otelBeforeAttach) {
            return Scope.noop();
        }

        if (log.isDebugEnabled()) {
            log.debugv("Setting Otel context: {0}", OpenTelemetryUtil.getSpanData(otelToAttach));
        }

        VertxContext.localContextData(vertxContext).put(OTEL_CONTEXT, otelToAttach);
        OpenTelemetryUtil.setMDCData(otelToAttach, vertxContext);

        return new Scope() {

            @Override

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure the Vert.x context is duplicated before attaching: call context.duplicate() and attach to the duplicated instance
  2. Only attach OTel contexts inside request-scoped/duplicated Vert.x contexts (e.g. within a route handler), not on root contexts
  3. Wrap work in vertx.executeBlocking or route handlers that Quarkus has already duplicated the context for
  4. Refactor custom instrumentation to use Context.root().with(...) capture inside the duplicated scope rather than attaching globally

Example fix

// before
Context vertxCtx = vertx.getOrCreateContext();
Scope scope = contextStorage.attach(vertxCtx, otelCtx);
// after
Context vertxCtx = vertx.getOrCreateContext().duplicate();
Scope scope = contextStorage.attach(vertxCtx, otelCtx);
Defensive patterns

Strategy: type-guard

Validate before calling

// check before attaching
static boolean safeToAttach(Context vertxContext) {
    return vertxContext != null
        && vertxContext.getLocal("__quarkus_otel_duplicated", false);
    // or use OrderedMarkers/duplication marker via
    // VertxContext.isDuplicatedContext(vertxContext) equivalent
}

Type guard

static boolean isDuplicatedContext(Context ctx) {
    // mirrors QuarkusContextStorage's own check: duplicated contexts carry
    // the duplication marker local
    return ctx != null
        && ctx.getLocal("__vertx.duplicated", false);
}

Try / catch

try {
    scope = contextStorage.attach(vertxContext, otelContext);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("duplicated Context")) {
        vertxContext = vertxContext.duplicate();
        scope = contextStorage.attach(vertxContext, otelContext);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling QuarkusContextStorage.attach(vertxContext, otelContext) with a Vert.x Context obtained outside a duplicated scope — e.g. Context from vertx.getOrCreateContext() on an event loop, a root context, or manual Context duplication skipped — while instrumenting code with OpenTelemetry scope management.

Common situations: Custom instrumentation or third-party libraries calling Context.current().with(...) and storage.attach(...) on a non-duplicated Vert.x context; running blocking/worker code that grabbed the wrong context; misuse of Vertx.currentContext() in startup or background threads.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/9dce1d7e245919a1. Report an issue: GitHub.