apolloconfig/apollo · warning · BadRequestException

operator should not be null or empty

Error message

operator should not be null or empty

What it means

Thrown by AppService.validateOperator when the operator string is blank (StringUtils.isBlank). Called from createAppInLocal and the update path as the first guard. BadRequestException → HTTP 400. The operator is normally the logged-in user id propagated by the controller; a blank value indicates the caller context was lost.

Source

Thrown at apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/AppService.java:90

      final RolePermissionService rolePermissionService, final FavoriteService favoriteService,
      final UserService userService, ApplicationEventPublisher publisher,
      final ApolloAuditLogApi apolloAuditLogApi, PortalSettings portalSettings) {
    this.appAPI = appAPI;
    this.appRepository = appRepository;
    this.clusterService = clusterService;
    this.appNamespaceService = appNamespaceService;
    this.roleInitializationService = roleInitializationService;
    this.rolePermissionService = rolePermissionService;
    this.favoriteService = favoriteService;
    this.userService = userService;
    this.apolloAuditLogApi = apolloAuditLogApi;
    this.publisher = publisher;
    this.portalSettings = portalSettings;
  }

  private static void validateOperator(String operator) {
    if (StringUtils.isBlank(operator)) {
      throw new BadRequestException("operator should not be null or empty");
    }
  }

  public List<App> findAll() {
    Iterable<App> apps = appRepository.findAll();

    return Lists.newArrayList(apps);
  }

  public PageDTO<App> findAll(Pageable pageable) {
    Page<App> apps = appRepository.findAll(pageable);

    return new PageDTO<>(apps.getContent(), pageable, apps.getTotalElements());
  }

  public PageDTO<App> searchByAppIdOrAppName(String query, Pageable pageable) {
    Page<App> apps = appRepository.findByAppIdContainingOrNameContaining(query, query, pageable);

View on GitHub (pinned to d95fc18d11)

Solutions

  1. Ensure the acting user's userId is always passed as operator (typically from UserInfoHolder).
  2. Reject requests at the controller layer when no authenticated user is present.
  3. In jobs/scripts, pass an explicit service-account operator id.

Example fix

// before
appService.createAppInLocal(app, null);

// after
String operator = userInfoHolder.getUser().getUserId();
if (StringUtils.isBlank(operator)) {
  throw new AccessDeniedException("no authenticated operator");
}
appService.createAppInLocal(app, operator);
Defensive patterns

Strategy: validation

Validate before calling

String operator = userInfoHolder.getUser().getUserId();
if (StringUtils.isBlank(operator)) {
  return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("no authenticated operator");
}

Type guard

boolean hasOperator(String op) { return !StringUtils.isBlank(op); }

Prevention

When it happens

Trigger: Calling createAppInLocal/updateApp with a null/empty/whitespace operator — e.g. controller passed null because the UserInfoHolder had no user, or a service-layer caller omitted the operator argument.

Common situations: Anonymous/unauthenticated call reaching the service layer; a test or job invokes AppService directly without setting an operator; a custom controller forgets to pass userInfoHolder.getUser().getUserId().

Related errors


AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14). Data as JSON: /api/errors/aa819eb87523a266. Report an issue: GitHub.