YunaiV/ruoyi-vue-pro · warning · ServiceException
423
423
Error message
请求失败,请稍后重试
What it means
DefaultLockFailureStrategy implements lock4j's LockFailureStrategy.onLockFailure. When a @Lock4j method cannot acquire the distributed lock (another holder owns it), it throws ServiceException(LOCKED, code 423, default '请求失败,请稍后重试'). This is by design: the request was rejected because a concurrent operation holds the lock.
Source
Thrown at yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/core/DefaultLockFailureStrategy.java:19
package cn.iocoder.yudao.framework.lock4j.core;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.baomidou.lock.LockFailureStrategy;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Method;
/**
* 自定义获取锁失败策略,抛出 {@link ServiceException} 异常
*/
@Slf4j
public class DefaultLockFailureStrategy implements LockFailureStrategy {
@Override
public void onLockFailure(String key, Method method, Object[] arguments) {
log.debug("[onLockFailure][线程:{} 获取锁失败,key:{} 获取失败:{} ]", Thread.currentThread().getName(), key, arguments);
throw new ServiceException(GlobalErrorCodeConstants.LOCKED);
}
}
View on GitHub (pinned to 0418084e22)
Solutions
- Reduce contention: narrow the @Lock4j compose key to the specific business entity.
- Increase acquireTimeout / expireTime on @Lock4j so the caller waits briefly instead of failing fast.
- Ensure long-running locked work completes or the lock TTL is appropriate so stale locks expire.
- If failure is acceptable UX, catch ServiceException(code==423) and show a friendly retry message.
Example fix
// before: coarse lock causes contention
@Lock4j(keys = {"#user.id"})
// after: lock the specific resource
@Lock4j(keys = {"#orderId"}, acquireTimeout = 3000, expire = 10000) Defensive patterns
Strategy: try-catch
Validate before calling
boolean acquired = redissonLock.tryLock(key, wait, lease, unit); if (!acquired) throw new ServiceException(LOCKED);
Type guard
null
Try / catch
try { method.invoke(); }
catch (ServiceException e) { if (e.getCode()==423) { backoffAndRetry(); return; } throw e; } Prevention
- Narrow the @Lock4j key to the specific entity
- Set an acquireTimeout so callers wait briefly
- Ensure locked work completes or TTL is appropriate
When it happens
Trigger: Two concurrent invocations of the same @Lock4j method with the same lock key; a previous invocation is slow and still holds the lock; a crashed holder left a lock that has not yet TTL-expired.
Common situations: User double-clicks a long-running action; a job runs in parallel on multiple nodes; lock key is too coarse so unrelated calls contend.
Related errors
AI-assisted analysis of YunaiV/ruoyi-vue-pro@0418084e22 (2026-08-14).
Data as JSON: /api/errors/9bd1e2c496de14df.
Report an issue: GitHub.