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
- Call the method through the CDI-managed bean (inject it) so ArC builds the correct intercepted context.
- If building contexts manually, add the Lock interceptor binding via ctx.getInterceptorBindings-style API before proceeding.
- Rebuild the app to regenerate interceptor chains (clean install) after a Quarkus upgrade.
- 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
- Always call @Lock-annotated methods on injected CDI beans, never on new instances
- Don't manually register or drive LockInterceptor in tests
- Rebuild after Quarkus upgrades so interceptor chains are regenerated
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
- Unsupported @Lock type found on business method ${method}
- Multiple @AroundInvoke interceptor methods declared on class
- Invalid injection of Interceptor<T> bean, can only be used i
- Type of injected Interceptor<T> does not match the type of t
- An interceptor method cannot be marked @Produces or @Dispose
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/ba255032a3a5c753.
Report an issue: GitHub.