{"record":{"id":"b6054096de1ee15e","repo":"apolloconfig/apollo","slug":"releaseids-should-be-comma-separated-numbers","errorCode":null,"errorMessage":"releaseIds should be comma separated numbers","messagePattern":"releaseIds should be comma separated numbers","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/InstanceController.java","lineNumber":105,"sourceCode":"  }\n\n  @Override\n  public ResponseEntity<List<OpenInstanceDTO>> getByReleasesAndNamespaceNotIn(String env,\n      String appId, String clusterName, String namespaceName, String releaseIds) {\n    if (shouldHideConfigToPortalUser(appId, env, clusterName, namespaceName)) {\n      return ResponseEntity.ok(Collections.emptyList());\n    }\n    checkConfigReadAllowed(appId, env, clusterName, namespaceName);\n    if (releaseIds == null || releaseIds.trim().isEmpty()) {\n      throw new BadRequestException(\"releaseIds should not be empty\");\n    }\n\n    Set<Long> releaseIdSet;\n    try {\n      releaseIdSet = RELEASE_ID_SPLITTER.splitToStream(releaseIds).map(Long::parseLong)\n          .collect(Collectors.toSet());\n    } catch (NumberFormatException ex) {\n      throw new BadRequestException(\"releaseIds should be comma separated numbers\");\n    }\n    if (releaseIdSet.isEmpty()) {\n      throw new BadRequestException(\"releaseIds should not be empty\");\n    }\n    return ResponseEntity.ok(OpenApiModelConverters.fromInstanceDTOs(instanceService\n        .getByReleasesNotIn(Env.valueOf(env), appId, clusterName, namespaceName, releaseIdSet)));\n  }\n\n  @Override\n  public ResponseEntity<Integer> getInstanceCountByNamespace(String env, String appId,\n      String clusterName, String namespaceName) {\n    if (shouldHideConfigToPortalUser(appId, env, clusterName, namespaceName)) {\n      return ResponseEntity.ok(0);\n    }\n    checkConfigReadAllowed(appId, env, clusterName, namespaceName);\n    return ResponseEntity.ok(instanceService.getInstanceCountByNamespace(appId, Env.valueOf(env),\n        clusterName, namespaceName));\n  }","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/apolloconfig/apollo/blob/d95fc18d112589efc09ddcbe1507047584d55251/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/InstanceController.java#L87-L123","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure every value in releaseIds is a valid base-10 integer that fits in a Long, e.g. releaseIds=123,456,789.","Validate each ID client-side with Long.parseLong() before constructing the query string.","Strip non-numeric characters and reject entries that fail parsing before sending the request."],"exampleFix":"// before — raw IDs from mixed source may contain non-numeric values\nString releaseIds = String.join(\",\", rawIds); // rawIds may contain \"v1.2.3\"\nclient.get(\"/instances/not-in-releases?releaseIds=\" + releaseIds);\n\n// after — parse and filter to valid longs\nList<Long> validIds = rawIds.stream()\n    .filter(s -> { try { Long.parseLong(s); return true; } catch (NumberFormatException e) { return false; } })\n    .map(Long::valueOf)\n    .collect(Collectors.toList());\nif (!validIds.isEmpty()) {\n    String releaseIds = validIds.stream().map(String::valueOf).collect(Collectors.joining(\",\"));\n    client.get(\"/instances/not-in-releases?releaseIds=\" + releaseIds);\n}","handlingStrategy":"validation","validationCode":"// Validate each release ID is numeric before joining into the query string\nfor (String id : releaseIdStrings) {\n    try {\n        Long.parseLong(id.trim());\n    } catch (NumberFormatException e) {\n        throw new IllegalArgumentException(\"Invalid release ID (not a number): \" + id);\n    }\n}\nString releaseIds = releaseIdStrings.stream().map(String::trim).collect(Collectors.joining(\",\"));","typeGuard":"private static boolean isValidReleaseIdList(String releaseIds) {\n    if (releaseIds == null || releaseIds.trim().isEmpty()) return false;\n    for (String token : releaseIds.split(\",\")) {\n        String trimmed = token.trim();\n        if (trimmed.isEmpty()) continue;\n        try { Long.parseLong(trimmed); } catch (NumberFormatException e) { return false; }\n    }\n    return true;\n}","tryCatchPattern":null,"preventionTips":["Type release IDs as Long/long in client code, not String, to prevent non-numeric input.","Validate with Long.parseLong() before serializing into query parameters.","In API client wrappers, add a pre-send validator for comma-separated numeric parameters."],"tags":["validation","openapi","instance","bad-request","input-validation","http-400","number-format"],"backgroundTag":null,"analyzedSha":"d95fc18d112589efc09ddcbe1507047584d55251","analyzedAt":"2026-08-14T04:00:05.477Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}