apolloconfig/apollo · error · BadRequestException

App is null

Error message

App is null

What it means

Thrown by AppController.createApp when the OpenCreateAppDTO request body's getApp() returns null. The createApp endpoint (POST /openapi/v1/apps or equivalent) expects a nested app object inside the request. If the client sends a body without the app field, or sends an empty JSON object, this guard fires. Results in HTTP 400.

Source

Thrown at apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/AppController.java:92

    this.consumerAuthUtil = consumerAuthUtil;
    this.consumerService = consumerService;
    this.appOpenApiService = appOpenApiService;
    this.userService = userService;
    this.userInfoHolder = userInfoHolder;
    this.rolePermissionService = rolePermissionService;
    this.unifiedPermissionValidator = unifiedPermissionValidator;
  }

  /**
   * @see com.ctrip.framework.apollo.portal.controller.AppController#create(AppModel)
   */
  @Transactional
  @PreAuthorize(value = "@unifiedPermissionValidator.hasCreateApplicationPermission()")
  @ApolloAuditLog(type = OpType.CREATE, name = "App.create")
  @Override
  public ResponseEntity<Void> createApp(OpenCreateAppDTO req) {
    if (null == req.getApp()) {
      throw new BadRequestException("App is null");
    }
    final OpenAppDTO app = req.getApp();
    if (!StringUtils.hasText(app.getAppId())) {
      throw new BadRequestException("AppId is null or blank");
    }
    validatePortalApp(app);
    String resolvedOperator = resolveOperator(app.getDataChangeCreatedBy());
    app.setDataChangeCreatedBy(resolvedOperator);
    app.setDataChangeLastModifiedBy(resolvedOperator);
    this.appOpenApiService.createApp(req, resolvedOperator);
    if (Boolean.TRUE.equals(req.getAssignAppRoleToSelf())
        && UserIdentityConstants.CONSUMER.equals(UserIdentityContextHolder.getAuthType())) {
      long consumerId = this.consumerAuthUtil.retrieveConsumerIdFromCtx();
      consumerService.assignAppRoleToConsumer(consumerId, app.getAppId(), resolvedOperator);
    }
    return ResponseEntity.ok().build();
  }

View on GitHub (pinned to d95fc18d11)

Solutions

  1. Ensure the request body includes a non-null app object with all required fields (appId, name, orgId, orgName, ownerName).
  2. Validate the JSON structure against the OpenAPI spec before sending.
  3. If using the Java client, call req.setApp(openAppDTO) before invoking the API.

Example fix

// before
OpenCreateAppDTO req = new OpenCreateAppDTO();
req.setAssignAppRoleToSelf(true);
// app field not set
api.createApp(req);

// after
OpenAppDTO app = new OpenAppDTO();
app.setAppId("my-app");
app.setName("My App");
app.setOrgId("org1");
app.setOrgName("My Org");
app.setOwnerName("admin");
OpenCreateAppDTO req = new OpenCreateAppDTO();
req.setApp(app);
req.setAssignAppRoleToSelf(true);
api.createApp(req);
Defensive patterns

Strategy: validation

Validate before calling

// Validate the request before calling createApp
if (req == null || req.getApp() == null) {
    throw new IllegalArgumentException("Request must contain a non-null app object");
}
appOpenApiService.createApp(req, operator);

Type guard

public static boolean isValidCreateAppRequest(OpenCreateAppDTO req) {
    return req != null && req.getApp() != null;
}

Prevention

When it happens

Trigger: Sending a POST request to create an app with a body like {} or {"assignAppRoleToSelf": true} that omits the "app" field. Also triggered if the deserialization of the app field fails silently (e.g., wrong JSON structure).

Common situations: An API client constructs OpenCreateAppDTO but forgets to call setApp(...). A JSON payload is malformed or the app field is named differently than expected by the OpenAPI spec. A client library version mismatch where the DTO shape changed.

Related errors


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