{"record":{"id":"8795230282abcee0","repo":"grpc/grpc-java","slug":"status-code-status-is-not-valid","errorCode":null,"errorMessage":"Status code ${status} is not valid","messagePattern":"Status code (.+?) is not valid","errorType":"validation","errorClass":"VerifyException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/grpc/internal/ServiceConfigUtil.java","lineNumber":170,"sourceCode":"    }\n    return getStatusCodesFromList(statuses);\n  }\n\n  private static Set<Status.Code> getStatusCodesFromList(List<?> statuses) {\n    EnumSet<Status.Code> codes = EnumSet.noneOf(Status.Code.class);\n    for (Object status : statuses) {\n      Status.Code code;\n      if (status instanceof Double) {\n        Double statusD = (Double) status;\n        int codeValue = statusD.intValue();\n        verify((double) codeValue == statusD, \"Status code %s is not integral\", status);\n        code = Status.fromCodeValue(codeValue).getCode();\n        verify(code.value() == statusD.intValue(), \"Status code %s is not valid\", status);\n      } else if (status instanceof String) {\n        try {\n          code = Status.Code.valueOf((String) status);\n        } catch (IllegalArgumentException iae) {\n          throw new VerifyException(\"Status code \" + status + \" is not valid\", iae);\n        }\n      } else {\n        throw new VerifyException(\n            \"Can not convert status code \" + status + \" to Status.Code, because its type is \"\n                + status.getClass());\n      }\n      codes.add(code);\n    }\n    return Collections.unmodifiableSet(codes);\n  }\n\n  static Set<Status.Code> getRetryableStatusCodesFromRetryPolicy(Map<String, ?> retryPolicy) {\n    String retryableStatusCodesKey = \"retryableStatusCodes\";\n    Set<Status.Code> codes = getListOfStatusCodesAsSet(retryPolicy, retryableStatusCodesKey);\n    verify(codes != null, \"%s is required in retry policy\", retryableStatusCodesKey);\n    verify(!codes.contains(Status.Code.OK), \"%s must not contain OK\", retryableStatusCodesKey);\n    return codes;\n  }","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/core/src/main/java/io/grpc/internal/ServiceConfigUtil.java#L152-L188","documentation":"ServiceConfigUtil.getStatusCodesFromList parses the retryable status codes list from a gRPC service config. Each entry must be either an integer equal to a valid Status code value or a string naming a Status.Code enum constant. When an integer entry does not match any real status code value, a VerifyException is thrown during config parsing.","triggerScenarios":"A service config's retryPolicy.retryableStatusCodes (or similar) list contains a numeric entry whose value does not correspond to a gRPC status code value (e.g. 7 corresponds to PERMISSION_DENIED, but 99 or 1234 does not). Reached via getListOfStatusCodesAsSet during service config resolution.","commonSituations":"Hand-written or tool-generated service config JSON with a typo in a numeric status code value; a config generated against a newer/different status code table; copy-pasted values from HTTP status codes instead of gRPC status codes.","solutions":["Check each numeric entry in retryableStatusCodes against the gRPC Status code value table (e.g. 0=OK, 3=INVALID_ARGUMENT, 8=RESOURCE_EXHAUSTED, 14=UNAVAILABLE, 16=UNAUTHENTICATED)","Prefer string names like \"UNAVAILABLE\" over numeric values to eliminate value-table mistakes","Remove or correct the offending entry and redeploy the service config","Validate the full service config with the grpc service config schema/validator before pushing it"],"exampleFix":"// before\n\"retryableStatusCodes\": [14, 99]\n// after\n\"retryableStatusCodes\": [\"UNAVAILABLE\", \"RESOURCE_EXHAUSTED\"]","handlingStrategy":"validation","validationCode":"// Validate before trusting config\nfor (Object status : statusCodes) {\n  if (status instanceof Integer) {\n    int v = (Integer) status;\n    if (io.grpc.Status.fromCodeValue(v) == io.grpc.Status.UNKNOWN && v != io.grpc.Status.UNKNOWN.getCode().value()) {\n      throw new IllegalArgumentException(\"Not a gRPC status code value: \" + v);\n    }\n  } else if (status instanceof String) {\n    io.grpc.Status.Code.valueOf((String) status); // throws if invalid\n  } else {\n    throw new IllegalArgumentException(\"Bad type: \" + status.getClass());\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  codes = ServiceConfigUtil.getListOfStatusCodesAsSet(rawList);\n} catch (VerifyException e) {\n  log.error(\"Bad retryableStatusCodes in service config: \" + e.getMessage());\n  throw new ConfigInvalidException(e);\n}","preventionTips":["Use string status names instead of numeric values in service configs","Lint service configs against the gRPC service config schema in CI","Keep a lookup table of gRPC code values when generating configs"],"tags":["grpc","service-config","retry-policy","status-codes"],"backgroundTag":"invalid-enum-value","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}