aeron-io/aeron · error · IllegalStateException
invalid end of key at index
Error message
invalid end of key at index <i> in <uri>
What it means
During ChannelUri.parse(), while accumulating a parameter key (PARAMS_KEY state), encountering '|' means the key section ended without '='; a key must be followed by '=' before the next param separator, so parse throws this IllegalStateException for the malformed URI.
Solutions
- Fix the URI at the reported index so each key is followed by '=' and a value before the next '|'
- Use ChannelUriStringBuilder instead of manual strings to guarantee well-formed key=value pairs
- Validate/normalize externally supplied URIs before parsing and catch IllegalStateException
Example fix
// before
ChannelUri uri = ChannelUri.parse("aeron:udp?endpoint|host:1234");
// after
ChannelUri uri = ChannelUri.parse("aeron:udp?endpoint=host:1234"); Defensive patterns
Strategy: validation
Validate before calling
static void validateParamSyntax(String uri) {
int q = uri.indexOf('?');
if (q < 0) return;
for (String p : uri.substring(q + 1).split("\\|")) {
if (!p.isEmpty() && !p.contains("=")) {
throw new IllegalArgumentException("param without '=': " + p);
}
}
} Type guard
static boolean allParamsHaveValues(String uri) {
int q = uri.indexOf('?');
if (q < 0) return true;
for (String p : uri.substring(q + 1).split("\\|")) {
if (!p.isEmpty() && p.indexOf('=') < 0) return false;
}
return true;
} Try / catch
try {
ChannelUri.parse(uri);
} catch (IllegalStateException e) {
log.error("Bad channel URI '{}': {}", uri, e.getMessage());
throw new IllegalArgumentException("Invalid channel URI", e);
} Prevention
- Always write params as key=value; never append a bare key before '|'
- Round-trip test generated URIs through ChannelUri.parse() in unit tests
- Prefer ChannelUriStringBuilder to eliminate manual separator mistakes
When it happens
Trigger: Calling ChannelUri.parse() on a URI where a param key is terminated by '|' instead of '=', e.g. "aeron:udp?endpoint|localhost:40456" or a trailing "|key" at the end of the params.
Common situations: Typos in hand-written channel URIs (missing '=' after a key); string-building code that forgets the '=' between name and value; copy/paste errors in configuration files.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- empty key not allowed at index
- no more input found, state=
- media type is mandatory
- value exceeds maximum permitted: value=
- must be a number
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/c62f6c8af188b2bf.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-client/src/main/java/io/aeron/ChannelUri.java:449
}
break;
case PARAMS_KEY:
if (c == '=')
{
if (builder.isEmpty())
{
throw new IllegalStateException("empty key not allowed at index " + i + " in " + uri);
}
key = builder.toString();
builder.setLength(0);
state = State.PARAMS_VALUE;
}
else
{
if (c == '|')
{
throw new IllegalStateException("invalid end of key at index " + i + " in " + uri);
}
builder.append(c);
}
break;
case PARAMS_VALUE:
if (c == '|')
{
params.put(key, builder.toString());
builder.setLength(0);
state = State.PARAMS_KEY;
}
else
{
builder.append(c);
}
break;
View on GitHub (pinned to 6d60124e15)