elastic/elasticsearch · error · IOException
Invalid DER: can't parse primitive entity
Error message
Invalid DER: can't parse primitive entity
What it means
Thrown by Asn1Object.getParser() when getParser() is called on a primitive (non-constructed) ASN.1 entity. Only constructed entities (tag bit 0x20 set, e.g. SEQUENCE, SET) have nested content that can be re-parsed; primitive entities hold a leaf value.
Source
Thrown at libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/DerParser.java:217
return length;
}
public byte[] getValue() {
return value;
}
public boolean isConstructed() {
return (tag & DerParser.CONSTRUCTED) == DerParser.CONSTRUCTED;
}
/**
* For constructed field, return a parser for its content.
*
* @return A parser for the construct.
*/
public DerParser getParser() throws IOException {
if (isConstructed() == false) {
throw new IOException("Invalid DER: can't parse primitive entity"); //$NON-NLS-1$
}
return new DerParser(value);
}
/**
* Get the value as integer
*
* @return BigInteger
*/
public BigInteger getInteger() throws IOException {
if (type != Type.INTEGER) throw new IOException("Invalid DER: object is not integer"); //$NON-NLS-1$
return new BigInteger(value);
}
public String getString() throws IOException {
View on GitHub (pinned to db6a809a66)
Solutions
- Regenerate the key with a standard tool: `openssl ecparam -genkey -name prime256v1 -out ec.pem` or `openssl pkcs8 -topk8`.
- If you are parsing custom DER, re-check the expected schema and ensure you only call getParser() on constructed elements.
- Use `isConstructed()` as a guard before calling getParser() to produce a clearer error.
- Inspect with `openssl asn1parse -inform DER -in key.der` to verify element types.
Example fix
// before: unconditional sub-parse
DerParser.Asn1Object choice = parser.readAsn1Object();
DerParser inner = choice.getParser(); // throws if primitive
// after: guard the call
if (choice.isConstructed() == false) {
throw new IOException("expected constructed element but found primitive tag 0x" + Integer.toHexString(choice.getTag()));
}
DerParser inner = choice.getParser(); Defensive patterns
Strategy: type-guard
Type guard
public static boolean isConstructed(DerParser.Asn1Object o) {
return o != null && o.isConstructed();
}
// Usage:
// DerParser.Asn1Object elem = parser.readAsn1Object();
// if (!isConstructed(elem)) throw new IOException("expected constructed element");
// DerParser inner = elem.getParser(); Prevention
- Always check isConstructed() before calling getParser().
- Validate element types against the expected schema before descending.
- Prefer PKCS#8 keys to avoid complex nested DER parsing paths.
When it happens
Trigger: Code calls asn1Object.getParser() on an object whose CONSTRUCTED bit (0x20) is not set. Common in parseEcDer (line 607) where the code calls choice.getParser() on the third element — if the input is misencoded and that element is primitive instead of constructed, this fires.
Common situations: Malformed EC private key where the expected [0] or [1] tagged constructed element is encoded as primitive, or a DER blob whose structure does not match the expected PKCS#1/PKCS#8/SEC1 layout.
Related errors
- Invalid DER: size of ASN.1 object to be parsed appears to be
- Invalid DER: stream too short, missing value. Could only rea
- Invalid DER: length missing
- Invalid DER: length field too big ({})
- Invalid DER: length too short
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/7ccb03e0737c96cc.
Report an issue: GitHub.