elastic/elasticsearch · error · IllegalStateException
cloudId {} must begin with a human readable identifier follo
Error message
cloudId {} must begin with a human readable identifier followed by a colon What it means
RestClient.builder(cloudId) accepts an optional human-readable prefix terminated by ':'. If a ':' is present but is the LAST character (nothing follows it), the cloudId is malformed — the Base64 payload that should follow the colon is empty, so parsing cannot proceed.
Source
Thrown at client/rest/src/main/java/org/elasticsearch/client/RestClient.java:163
this.warningsHandler = strictDeprecationMode ? WarningsHandler.STRICT : WarningsHandler.PERMISSIVE;
this.compressionEnabled = compressionEnabled;
this.metaHeaderEnabled = metaHeaderEnabled;
setNodes(nodes);
}
/**
* Returns a new {@link RestClientBuilder} to help with {@link RestClient} creation.
* Creates a new builder instance and sets the nodes that the client will send requests to.
*
* @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) {View on GitHub (pinned to db6a809a66)
Solutions
- Re-copy the full cloudId from Elastic Cloud console (it contains the Base64 payload after the colon).
- Strip the human-readable prefix entirely if you only have the Base64 part — builder accepts a colon-less cloudId too.
- Validate the cloudId shape (contains ':' followed by non-empty Base64) before calling builder.
Example fix
// before
RestClient.builder("my-cluster:"); // empty payload after colon
// after
RestClient.builder("my-cluster:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRlbGFzdGljc2VhcmNoJGtpYmFuYQ=="); Defensive patterns
Strategy: validation
Validate before calling
static boolean cloudIdHasPayload(String cloudId) {
int ci = cloudId.indexOf(':');
return ci < 0 || ci < cloudId.length() - 1; // colon-less, or colon followed by payload
}
if (!cloudIdHasPayload(cloudId)) throw new IllegalArgumentException("cloudId missing Base64 payload after colon");
RestClient.builder(cloudId); Try / catch
try { RestClient.builder(cloudId); } catch (IllegalStateException e) { /* prompt user to re-copy cloudId from Elastic Cloud */ } Prevention
- Copy the cloudId verbatim from the Elastic Cloud console 'Cloud ID' field.
- Treat the human-readable prefix as optional decoration; the Base64 payload is mandatory.
- Validate cloudId shape at config load time.
When it happens
Trigger: Passing a cloudId string like 'my-cluster:' (colon with no Base64 after it); a truncated/copy-paste cloudId from the Elastic Cloud console; a cloudId whose prefix colon was added by mistake.
Common situations: User copies the human-readable label from Elastic Cloud but misses the Base64 portion; trailing whitespace or newline truncation; manual concatenation that drops the payload.
Related errors
- cloudId {} did not decode to a cluster identifier correctly
- 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/433549e4dffa0d5e.
Report an issue: GitHub.