apolloconfig/apollo · error · BadRequestException
Invalid encoded key
Error message
Invalid encoded key
What it means
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.
Source
Thrown at apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/ItemController.java:403
if (!hasPermission) {
noPermissionNamespace = namespaceIdentifier;
break;
}
}
if (!hasPermission) {
throw new AccessDeniedException(String
.format("You don't have the permission to modify namespace: %s", noPermissionNamespace));
}
}
private String decodeBase64(String key) {
try {
return decodeBase64(key, Base64.getDecoder());
} catch (IllegalArgumentException standardBase64Exception) {
try {
return decodeBase64(key, Base64.getUrlDecoder());
} catch (IllegalArgumentException urlBase64Exception) {
throw new BadRequestException("Invalid encoded key");
}
}
}
private String decodeBase64(String key, Base64.Decoder decoder) {
return new String(decoder.decode(key), StandardCharsets.UTF_8);
}
void doSyntaxCheck(NamespaceTextModel model) {
NamespaceTextSyntaxChecker.check(model);
}
}
View on GitHub (pinned to d95fc18d11)
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.
Example fix
// before
String url = "/items/timeout.ms"; // raw key -> 400
// after
String encoded = Base64.getEncoder().encodeToString("timeout.ms".getBytes(StandardCharsets.UTF_8));
String url = "/items/" + encoded; Defensive patterns
Strategy: validation
Validate before calling
// Validate Base64 round-trip locally before the call.
import java.util.Base64;
String rawKey = "timeout.ms";
String encoded = Base64.getEncoder().encodeToString(rawKey.getBytes(StandardCharsets.UTF_8));
// sanity: decodes with standard OR url decoder
try { Base64.getDecoder().decode(encoded); }
catch (IllegalArgumentException e) { Base64.getUrlDecoder().decode(encoded); } // throws if truly invalid -> fix before sending Type guard
null
Try / catch
try {
client.getItem(appId, env, cluster, ns, encodedKey);
} catch (HttpClientErrorException.BadRequest e) {
if (e.getResponseBodyAsString().contains("Invalid encoded key")) {
// re-encode the raw key and retry once
encodedKey = Base64.getEncoder().encodeToString(rawKey.getBytes(StandardCharsets.UTF_8));
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- create namespace failed for: %s
- userIds should not be null or empty
- Consumer already exist
- Token is Illegal
- Namespace's role does not exist. Please check whether namesp
AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14).
Data as JSON: /api/errors/f539cb7e83ce2a00.
Report an issue: GitHub.