apolloconfig/apollo · error · BadRequestException

releaseIds should be comma separated numbers

Error message

releaseIds should be comma separated numbers

What it means

Thrown by InstanceController.getByReleasesAndNamespaceNotIn when the releaseIds parameter contains values that are not parseable as Long. The RELEASE_ID_SPLITTER splits the comma-separated string and Long::parseLong throws NumberFormatException, which is caught and rethrown as this BadRequestException. Maps to HTTP 400 BadRequestException.

Source

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

  }

  @Override
  public ResponseEntity<List<OpenInstanceDTO>> getByReleasesAndNamespaceNotIn(String env,
      String appId, String clusterName, String namespaceName, String releaseIds) {
    if (shouldHideConfigToPortalUser(appId, env, clusterName, namespaceName)) {
      return ResponseEntity.ok(Collections.emptyList());
    }
    checkConfigReadAllowed(appId, env, clusterName, namespaceName);
    if (releaseIds == null || releaseIds.trim().isEmpty()) {
      throw new BadRequestException("releaseIds should not be empty");
    }

    Set<Long> releaseIdSet;
    try {
      releaseIdSet = RELEASE_ID_SPLITTER.splitToStream(releaseIds).map(Long::parseLong)
          .collect(Collectors.toSet());
    } catch (NumberFormatException ex) {
      throw new BadRequestException("releaseIds should be comma separated numbers");
    }
    if (releaseIdSet.isEmpty()) {
      throw new BadRequestException("releaseIds should not be empty");
    }
    return ResponseEntity.ok(OpenApiModelConverters.fromInstanceDTOs(instanceService
        .getByReleasesNotIn(Env.valueOf(env), appId, clusterName, namespaceName, releaseIdSet)));
  }

  @Override
  public ResponseEntity<Integer> getInstanceCountByNamespace(String env, String appId,
      String clusterName, String namespaceName) {
    if (shouldHideConfigToPortalUser(appId, env, clusterName, namespaceName)) {
      return ResponseEntity.ok(0);
    }
    checkConfigReadAllowed(appId, env, clusterName, namespaceName);
    return ResponseEntity.ok(instanceService.getInstanceCountByNamespace(appId, Env.valueOf(env),
        clusterName, namespaceName));
  }

View on GitHub (pinned to d95fc18d11)

Solutions

  1. Ensure every value in releaseIds is a valid base-10 integer that fits in a Long, e.g. releaseIds=123,456,789.
  2. Validate each ID client-side with Long.parseLong() before constructing the query string.
  3. Strip non-numeric characters and reject entries that fail parsing before sending the request.

Example fix

// before — raw IDs from mixed source may contain non-numeric values
String releaseIds = String.join(",", rawIds); // rawIds may contain "v1.2.3"
client.get("/instances/not-in-releases?releaseIds=" + releaseIds);

// after — parse and filter to valid longs
List<Long> validIds = rawIds.stream()
    .filter(s -> { try { Long.parseLong(s); return true; } catch (NumberFormatException e) { return false; } })
    .map(Long::valueOf)
    .collect(Collectors.toList());
if (!validIds.isEmpty()) {
    String releaseIds = validIds.stream().map(String::valueOf).collect(Collectors.joining(","));
    client.get("/instances/not-in-releases?releaseIds=" + releaseIds);
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate each release ID is numeric before joining into the query string
for (String id : releaseIdStrings) {
    try {
        Long.parseLong(id.trim());
    } catch (NumberFormatException e) {
        throw new IllegalArgumentException("Invalid release ID (not a number): " + id);
    }
}
String releaseIds = releaseIdStrings.stream().map(String::trim).collect(Collectors.joining(","));

Type guard

private static boolean isValidReleaseIdList(String releaseIds) {
    if (releaseIds == null || releaseIds.trim().isEmpty()) return false;
    for (String token : releaseIds.split(",")) {
        String trimmed = token.trim();
        if (trimmed.isEmpty()) continue;
        try { Long.parseLong(trimmed); } catch (NumberFormatException e) { return false; }
    }
    return true;
}

Prevention

When it happens

Trigger: GET .../instances/not-in-releases?releaseIds=123,abc,456 where 'abc' is not numeric. Also triggered by releaseIds=12.5 (decimal) or releaseIds=0x10 (hex notation) since Long.parseLong does not accept these forms.

Common situations: Release IDs are mistakenly mixed with namespace names or version strings. A client serializes objects instead of their ID fields. Decimal-formatted IDs from another system are passed without conversion to integer.

Related errors


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