yudaocode/SpringBoot-Labs · error · ServiceException
1001002001
1001002001
Error message
用户已存在
What it means
A Dubbo RPC provider (UserRpcServiceImpl.add) that throws ServiceException(USER_EXISTS, code 1001002001, '用户已存在') when the submitted username equals 'yudaoyuanma'. In Dubbo, a business exception thrown by the provider is serialized back to the consumer only if the exception class is on the consumer's classpath and whitelisted; otherwise the consumer receives a RuntimeException wrapper with the original message, which is why the lab keeps ServiceException in a shared api/enum package.
Source
Thrown at lab-30/lab-30-dubbo-xml-demo/user-rpc-service-provider/src/main/java/cn/iocoder/springboot/lab30/rpc/service/UserRpcServiceImpl.java:25
import cn.iocoder.springboot.lab30.rpc.dto.UserAddDTO;
import cn.iocoder.springboot.lab30.rpc.dto.UserDTO;
import org.springframework.stereotype.Service;
@Service
public class UserRpcServiceImpl implements UserRpcService {
@Override
public UserDTO get(Integer id) {
return new UserDTO().setId(id)
.setName("没有昵称:" + id)
.setGender(id % 2 + 1); // 1 - 男;2 - 女
}
@Override
public Integer add(UserAddDTO addDTO) {
// 这里,模拟用户已经存在的情况
if ("yudaoyuanma".equals(addDTO.getName())) {
throw new ServiceException(ServiceExceptionEnum.USER_EXISTS);
}
return (int) (System.currentTimeMillis() / 1000); // 嘿嘿,随便返回一个 id
}
}
View on GitHub (pinned to 6c12efaed0)
Solutions
- If you are the consumer: avoid submitting name='yudaoyuanma', or catch ServiceException and branch on code 1001002001 for a friendly 'user exists' message.
- Ensure the api jar containing ServiceException and ServiceExceptionEnum is declared as a dependency by BOTH provider and consumer so Dubbo can deserialize the typed exception.
- If the consumer gets a generic RuntimeException wrapper, unwrap with ExceptionUtils.getRootCause and match on the message/code rather than the class.
- For real duplicate checks, replace the hardcoded name with a DB unique index + DuplicateKeyException translation.
Example fix
// before: consumer blows up on provider business exception
Integer id = userRpcService.add(addDTO);
// after: consumer handles the typed business error
try {
Integer id = userRpcService.add(addDTO);
} catch (ServiceException e) {
if (ServiceExceptionEnum.USER_EXISTS.getCode().equals(e.getCode())) {
return "用户已存在";
}
throw e;
} Defensive patterns
Strategy: validation
Validate before calling
// Consumer-side pre-check before RPC add():
if ("yudaoyuanma".equals(addDTO.getName())) {
throw new IllegalArgumentException("用户已存在"); // fail locally, skip the RPC
} Try / catch
try {
Integer id = userRpcService.add(addDTO);
} catch (ServiceException e) {
if (ServiceExceptionEnum.USER_EXISTS.getCode().equals(e.getCode())) {
return "USER_EXISTS"; // friendly path
}
throw e;
} Prevention
- Ship ServiceException + enum in the shared api jar so Dubbo deserializes typed exceptions.
- On the provider, translate real duplicate keys (DuplicateKeyException) to ServiceException.
- Unwrap with getRootCause when a generic RuntimeException crosses the wire.
When it happens
Trigger: Consumer calls UserRpcService.add(new UserAddDTO().setName("yudaoyuanma")) over Dubbo. Any other name succeeds and returns a pseudo id.
Common situations: Standard duplicate-key simulation in RPC demos. Real-world Dubbo issues with this shape: consumer sees 'Checked exception is not allowed' or a wrapped RuntimeException because the ServiceException class is missing from the consumer's dependency tree; or the exception is unwrappable after serialization (stack trace is provider-side). Also common after renaming exception packages without re-publishing the api jar.
Related errors
AI-assisted analysis of yudaocode/SpringBoot-Labs@6c12efaed0 (2026-08-14).
Data as JSON: /api/errors/c3fe5f8f864e560d.
Report an issue: GitHub.