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

  1. If you are the consumer: avoid submitting name='yudaoyuanma', or catch ServiceException and branch on code 1001002001 for a friendly 'user exists' message.
  2. 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.
  3. If the consumer gets a generic RuntimeException wrapper, unwrap with ExceptionUtils.getRootCause and match on the message/code rather than the class.
  4. 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

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.