elastic/elasticsearch · error · IllegalStateException
cloudId {} did not decode to a cluster identifier correctly
Error message
cloudId {} did not decode to a cluster identifier correctly What it means
After stripping the optional human-readable prefix and Base64-decoding, the cloudId must split on '$' into exactly three parts: domain[:port], elasticsearch id, kibana id. Any other count means the cloudId is structurally invalid and the cluster endpoint cannot be derived.
Source
Thrown at client/rest/src/main/java/org/elasticsearch/client/RestClient.java:173
* @param cloudId a valid elastic cloud cloudId that will route to a cluster. The cloudId is located in
* the user console https://cloud.elastic.co and will resemble a string like the following
* optionalHumanReadableName:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRlbGFzdGljc2VhcmNoJGtpYmFuYQ==
*/
public static RestClientBuilder builder(String cloudId) {
// there is an optional first portion of the cloudId that is a human readable string, but it is not used.
if (cloudId.contains(":")) {
if (cloudId.indexOf(':') == cloudId.length() - 1) {
throw new IllegalStateException("cloudId " + cloudId + " must begin with a human readable identifier followed by a colon");
}
cloudId = cloudId.substring(cloudId.indexOf(':') + 1);
}
String decoded = new String(Base64.getDecoder().decode(cloudId), UTF_8);
// once decoded the parts are separated by a $ character.
// they are respectively domain name and optional port, elasticsearch id, kibana id
String[] decodedParts = decoded.split("\\$");
if (decodedParts.length != 3) {
throw new IllegalStateException("cloudId " + cloudId + " did not decode to a cluster identifier correctly");
}
// domain name and optional port
String[] domainAndMaybePort = decodedParts[0].split(":", 2);
String domain = domainAndMaybePort[0];
int port;
if (domainAndMaybePort.length == 2) {
try {
port = Integer.parseInt(domainAndMaybePort[1]);
} catch (NumberFormatException nfe) {
throw new IllegalStateException("cloudId " + cloudId + " does not contain a valid port number");
}
} else {
port = 443;
}
String url = decodedParts[1] + "." + domain;View on GitHub (pinned to db6a809a66)
Solutions
- Re-copy the cloudId verbatim from the Elastic Cloud deployment's 'Cloud ID' field.
- Verify the Base64 decodes to a string with exactly two '$' separators.
- If migrating deployments, generate a fresh cloudId for the new deployment.
Example fix
// before
RestClient.builder("not-valid-base64-payload");
// after
RestClient.builder("MyDeploy:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRlbGFzdGljc2VhcmNoJGtpYmFuYQ=="); Defensive patterns
Strategy: validation
Validate before calling
static boolean cloudIdDecodesToThreeParts(String cloudId) {
String payload = cloudId.contains(":") ? cloudId.substring(cloudId.indexOf(':') + 1) : cloudId;
try {
String decoded = new String(Base64.getDecoder().decode(payload));
return decoded.split("\\$").length == 3;
} catch (IllegalArgumentException e) { return false; }
} Try / catch
try { RestClient.builder(cloudId); } catch (IllegalStateException e) { /* re-copy cloudId; it is malformed */ } Prevention
- Use the cloudId exactly as exported by Elastic Cloud.
- Don't synthesize cloudIds by hand.
- Validate the decoded structure at config load time.
When it happens
Trigger: Passing a cloudId whose decoded form has 2 or 4+ '$'-segments; a cloudId from a different Elastic deployment format; a corrupted/truncated Base64 that decodes to garbage without the expected separators.
Common situations: Wrong cloudId copied (e.g. from a Kibana-only or APM deployment); Base64 string trimmed or padded incorrectly; using a placeholder/example cloudId that is not a real one.
Related errors
- cloudId {} must begin with a human readable identifier follo
- cloudId {} does not contain a valid port number
- hosts must not be null nor empty
- nodes must not be null or empty
- Can't create extra config file from {} for {} as it does not
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/3848f611cf0dc380.
Report an issue: GitHub.