quarkusio/quarkus · error · jakarta.enterprise.context.control.LockException

@Lock binding not found on business method ${method}

Error message

@Lock binding not found on business method ${method}

What it means

LockInterceptor.getLock() expects the InvocationContext to carry a @Lock interceptor binding; if absent it throws LockException. The code comment notes this should never happen because the interceptor is only activated by that binding — hitting it means the interceptor was invoked with the wrong binding set (container bug, wrong interceptor wiring, or a reflection-built context in tests).

Source

Thrown at independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/LockInterceptor.java:111

                    throw new LockException("Read lock not acquired in " + lock.unit().toMillis(time) + " ms");
                }
            } else {
                rwl.readLock().lock();
                locked = true;
            }
            return ctx.proceed();
        } finally {
            if (locked) {
                rwl.readLock().unlock();
            }
        }
    }

    Lock getLock(ArcInvocationContext ctx) {
        Lock lock = ctx.findIterceptorBinding(Lock.class);
        if (lock == null) {
            // This should never happen
            throw new LockException("@Lock binding not found on business method " + ctx.getMethod());
        }
        return lock;
    }

}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Call the method through the CDI-managed bean (inject it) so ArC builds the correct intercepted context.
  2. If building contexts manually, add the Lock interceptor binding via ctx.getInterceptorBindings-style API before proceeding.
  3. Rebuild the app to regenerate interceptor chains (clean install) after a Quarkus upgrade.
  4. Remove manual registration of LockInterceptor; rely on the container's automatic binding discovery.

Example fix

// before
new MyBean().read(); // raw instance, wrong context
// after
@Inject MyBean bean;
bean.read(); // container-managed, binding present
Defensive patterns

Strategy: type-guard

Validate before calling

if (bean instanceof Intercepted == false /* or use CDI.current().select */) {
    throw new IllegalStateException("Invoke via CDI-managed bean so @Lock binding is present");
}

Type guard

<T> T requireManaged(Instance<T> instance, Class<T> type) {
    T bean = instance.get();
    if (bean == null) throw new IllegalStateException("No managed bean for " + type);
    return bean;
}

Try / catch

try {
    return method.invoke(managedBean, args);
} catch (InvocationTargetException e) {
    if (e.getCause() instanceof LockException) {
        throw new IllegalStateException("@Lock binding missing — use the container-managed proxy", e.getCause());
    }
    throw e;
}

Prevention

When it happens

Trigger: Invoking an intercepted method through a manually constructed InvocationContext (e.g. custom AOP or test harness) that activates LockInterceptor without adding the Lock binding; container misconfiguration where interceptor bindings were lost.

Common situations: Unit tests invoking methods on raw (unproxied) or hand-wired interception contexts; upgrading Quarkus where binding propagation changed; registering LockInterceptor manually without its binding.

Related errors


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