{"record":{"id":"b14db1b435ace75c","repo":"quarkusio/quarkus","slug":"unsupported-lock-type-found-on-business-method","errorCode":null,"errorMessage":"Unsupported @Lock type found on business method ${method}","messagePattern":"Unsupported @Lock type found on business method (.+?)","errorType":"exception","errorClass":"jakarta.enterprise.context.control.LockException","httpStatus":null,"severity":"error","filePath":"independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/LockInterceptor.java","lineNumber":38,"sourceCode":"public class LockInterceptor {\n\n    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();\n\n    // This lock is used exclusively to synchronize the block where we release all read locks and aquire the write lock\n    private final ReentrantLock rl = new ReentrantLock();\n\n    @AroundInvoke\n    Object lock(ArcInvocationContext ctx) throws Exception {\n        Lock lock = getLock(ctx);\n        switch (lock.value()) {\n            case WRITE:\n                return writeLock(lock, ctx);\n            case READ:\n                return readLock(lock, ctx);\n            case NONE:\n                return ctx.proceed();\n            default:\n                throw new LockException(\"Unsupported @Lock type found on business method \" + ctx.getMethod());\n        }\n    }\n\n    private Object writeLock(Lock lock, InvocationContext ctx) throws Exception {\n        long time = lock.time();\n        int readHoldCount = rwl.getReadHoldCount();\n        boolean locked = false;\n\n        try {\n            if (readHoldCount > 0) {\n                rl.lock();\n            }\n            try {\n                if (readHoldCount > 0) {\n                    // Release all read locks hold by the current thread before acquiring the write lock\n                    for (int i = 0; i < readHoldCount; i++) {\n                        rwl.readLock().unlock();\n                    }","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/arc/runtime/src/main/java/io/quarkus/arc/impl/LockInterceptor.java#L20-L56","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n@Lock(someCustomType)\npublic String read() { ... }\n// after\n@Lock(LockType.READ)\npublic String read() { ... }","handlingStrategy":"validation","validationCode":"Lock l = ctx.findIterceptorBinding(Lock.class);\nif (l == null || (l.value() != LockType.READ && l.value() != LockType.WRITE && l.value() != LockType.NONE)) {\n    throw new IllegalStateException(\"Invalid @Lock value: \" + (l == null ? \"null\" : l.value()));\n}","typeGuard":"boolean isValidLockType(LockType t) { return t == LockType.READ || t == LockType.WRITE || t == LockType.NONE; }","tryCatchPattern":"try {\n    return invocationContext.proceed();\n} catch (LockException e) {\n    throw new IllegalStateException(\"Unsupported @Lock binding on \" + method, e);\n}","preventionTips":["Only use the three LockType constants in @Lock annotations","Keep the lock extension and ArC runtime versions aligned","Avoid dynamically constructing Lock annotation instances"],"tags":["cdi","interceptor","locking","arc"],"backgroundTag":"invalid-enum-annotation-value","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}