{"record":{"id":"f539cb7e83ce2a00","repo":"apolloconfig/apollo","slug":"invalid-encoded-key","errorCode":null,"errorMessage":"Invalid encoded key","messagePattern":"Invalid encoded key","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/ItemController.java","lineNumber":403,"sourceCode":"      if (!hasPermission) {\n        noPermissionNamespace = namespaceIdentifier;\n        break;\n      }\n    }\n    if (!hasPermission) {\n      throw new AccessDeniedException(String\n          .format(\"You don't have the permission to modify namespace: %s\", noPermissionNamespace));\n    }\n  }\n\n  private String decodeBase64(String key) {\n    try {\n      return decodeBase64(key, Base64.getDecoder());\n    } catch (IllegalArgumentException standardBase64Exception) {\n      try {\n        return decodeBase64(key, Base64.getUrlDecoder());\n      } catch (IllegalArgumentException urlBase64Exception) {\n        throw new BadRequestException(\"Invalid encoded key\");\n      }\n    }\n  }\n\n  private String decodeBase64(String key, Base64.Decoder decoder) {\n    return new String(decoder.decode(key), StandardCharsets.UTF_8);\n  }\n\n  void doSyntaxCheck(NamespaceTextModel model) {\n    NamespaceTextSyntaxChecker.check(model);\n  }\n}\n","sourceCodeStart":385,"sourceCodeEnd":416,"githubUrl":"https://github.com/apolloconfig/apollo/blob/d95fc18d112589efc09ddcbe1507047584d55251/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/ItemController.java#L385-L416","documentation":"HTTP 400 (BadRequestException). Thrown by ItemController.decodeBase64 when the {key} path parameter supplied to getItem/updateItem/deleteItem cannot be decoded as EITHER standard Base64 or URL-safe Base64 (both java.util.Base64 decoders raise IllegalArgumentException). Apollo OpenAPI requires item keys to be Base64-encoded so keys containing '/', '+', and special characters survive URL transport.","triggerScenarios":"GET/PUT/DELETE /openapi/v1/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/items/{key} where {key} is the raw, un-encoded item key; or a key that was double-encoded, truncated by a URL shortener, or mangled by an HTTP client that URL-encoded the Base64 string a second time.","commonSituations":"Caller passed the plaintext key 'timeout.ms' directly instead of Base64('timeout.ms'); copy-paste from a browser that percent-encoded '+', '/', '='; a key containing spaces or non-ASCII passed through un-encoded; version mismatch where an older client expected plaintext keys.","solutions":["Base64-encode the item key before placing it in the URL path using standard Base64 (URL-safe also accepted).","If the key is already Base64 but still failing, ensure your HTTP client is not additionally percent-encoding the Base64 characters (+,/,=) and not double-encoding.","Trim whitespace/newlines that some Base64 encoders append before sending.","Verify the exact encoded string round-trips locally with Base64.getDecoder().decode(...) before the call."],"exampleFix":"// before\nString url = \"/items/timeout.ms\"; // raw key -> 400\n\n// after\nString encoded = Base64.getEncoder().encodeToString(\"timeout.ms\".getBytes(StandardCharsets.UTF_8));\nString url = \"/items/\" + encoded;","handlingStrategy":"validation","validationCode":"// Validate Base64 round-trip locally before the call.\nimport java.util.Base64;\nString rawKey = \"timeout.ms\";\nString encoded = Base64.getEncoder().encodeToString(rawKey.getBytes(StandardCharsets.UTF_8));\n// sanity: decodes with standard OR url decoder\ntry { Base64.getDecoder().decode(encoded); }\ncatch (IllegalArgumentException e) { Base64.getUrlDecoder().decode(encoded); } // throws if truly invalid -> fix before sending","typeGuard":"null","tryCatchPattern":"try {\n  client.getItem(appId, env, cluster, ns, encodedKey);\n} catch (HttpClientErrorException.BadRequest e) {\n  if (e.getResponseBodyAsString().contains(\"Invalid encoded key\")) {\n    // re-encode the raw key and retry once\n    encodedKey = Base64.getEncoder().encodeToString(rawKey.getBytes(StandardCharsets.UTF_8));\n  }\n}","preventionTips":["Always Base64-encode item keys in the URL path; never send raw keys.","Disable auto percent-encoding of '+','/','=' in your HTTP client for this path segment.","Strip trailing newlines/whitespace from encoder output before sending."],"tags":["apollo-portal","openapi","base64","bad-request","item","encoding"],"backgroundTag":null,"analyzedSha":"d95fc18d112589efc09ddcbe1507047584d55251","analyzedAt":"2026-08-14T04:00:05.477Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}