quarkusio/quarkus · error · jakarta.enterprise.context.control.LockException
Unsupported @Lock type found on business method ${method}
Error message
Unsupported @Lock type found on business method ${method} What it means
The @Lock interceptor (io.quarkus.arc.lock / LockInterceptor) switches on the LockType value of the @Lock annotation (READ, WRITE, NONE). Any other value hits the default branch and throws a LockException. Since LockType is an enum with only these values, this is nearly always a custom/bogus annotation binding or a version mismatch where LockType gained a value an old interceptor doesn't know.
Source
Thrown at independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/LockInterceptor.java:38
public class LockInterceptor {
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
// This lock is used exclusively to synchronize the block where we release all read locks and aquire the write lock
private final ReentrantLock rl = new ReentrantLock();
@AroundInvoke
Object lock(ArcInvocationContext ctx) throws Exception {
Lock lock = getLock(ctx);
switch (lock.value()) {
case WRITE:
return writeLock(lock, ctx);
case READ:
return readLock(lock, ctx);
case NONE:
return ctx.proceed();
default:
throw new LockException("Unsupported @Lock type found on business method " + ctx.getMethod());
}
}
private Object writeLock(Lock lock, InvocationContext ctx) throws Exception {
long time = lock.time();
int readHoldCount = rwl.getReadHoldCount();
boolean locked = false;
try {
if (readHoldCount > 0) {
rl.lock();
}
try {
if (readHoldCount > 0) {
// Release all read locks hold by the current thread before acquiring the write lock
for (int i = 0; i < readHoldCount; i++) {
rwl.readLock().unlock();
}View on GitHub (pinned to e1c734241f)
Solutions
- Use only @Lock(LockType.READ), @Lock(LockType.WRITE), or @Lock(LockType.NONE) on the business method.
- Align versions of io.quarkus.arc / the lock extension so LockType and LockInterceptor come from the same release.
- If building the Lock annotation dynamically, set value() to a valid LockType constant.
- Remove custom interceptor bindings that mimic @Lock and use the official annotation.
Example fix
// before
@Lock(someCustomType)
public String read() { ... }
// after
@Lock(LockType.READ)
public String read() { ... } Defensive patterns
Strategy: validation
Validate before calling
Lock l = ctx.findIterceptorBinding(Lock.class);
if (l == null || (l.value() != LockType.READ && l.value() != LockType.WRITE && l.value() != LockType.NONE)) {
throw new IllegalStateException("Invalid @Lock value: " + (l == null ? "null" : l.value()));
} Type guard
boolean isValidLockType(LockType t) { return t == LockType.READ || t == LockType.WRITE || t == LockType.NONE; } Try / catch
try {
return invocationContext.proceed();
} catch (LockException e) {
throw new IllegalStateException("Unsupported @Lock binding on " + method, e);
} Prevention
- Only use the three LockType constants in @Lock annotations
- Keep the lock extension and ArC runtime versions aligned
- Avoid dynamically constructing Lock annotation instances
When it happens
Trigger: A bean method annotated @Lock resolves (at invocation time) to a Lock instance whose value() is not READ/WRITE/NONE — e.g. a synthetic or mis-mapped @Lock binding, or a custom LockType in a newer/older jar than LockInterceptor.
Common situations: Version mismatch between the extension defining @Lock/LockType and the ArC runtime; hand-built or proxied Lock annotation instances with a null/foreign value; reflection-built annotation mocks in tests.
Related errors
- @Lock binding not 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/b14db1b435ace75c.
Report an issue: GitHub.