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

  1. Use only @Lock(LockType.READ), @Lock(LockType.WRITE), or @Lock(LockType.NONE) on the business method.
  2. Align versions of io.quarkus.arc / the lock extension so LockType and LockInterceptor come from the same release.
  3. If building the Lock annotation dynamically, set value() to a valid LockType constant.
  4. 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

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


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