elastic/elasticsearch · error · IOException

Invalid DER: object is not a string

Error message

Invalid DER: object is not a string

What it means

Thrown by Asn1Object.getString() in its default branch when the element type does not match any supported string type (OCTET_STRING, NUMERIC/PRINTABLE/VIDEOTEX/IA5/GRAPHIC/ISO646/GENERAL, BMP, UTF8) and is not UNIVERSAL_STRING. The parser refuses to interpret an arbitrary tag as text.

Source

Thrown at libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/DerParser.java:264

                case Type.GRAPHIC_STRING:
                case Type.ISO646_STRING:
                case Type.GENERAL_STRING:
                    encoding = "ISO-8859-1"; //$NON-NLS-1$
                    break;

                case Type.BMP_STRING:
                    encoding = "UTF-16BE"; //$NON-NLS-1$
                    break;

                case Type.UTF8_STRING:
                    encoding = "UTF-8"; //$NON-NLS-1$
                    break;

                case Type.UNIVERSAL_STRING:
                    throw new IOException("Invalid DER: can't handle UCS-4 string"); //$NON-NLS-1$

                default:
                    throw new IOException("Invalid DER: object is not a string"); //$NON-NLS-1$
            }

            return new String(value, encoding);
        }

        public String getOid() throws IOException {

            if (type != Type.OBJECT_OID) {
                throw new IOException("Ivalid DER: object is not object OID");
            }
            StringBuilder sb = new StringBuilder(64);
            switch (value[0] / 40) {
                case 0 -> sb.append('0');
                case 1 -> {
                    sb.append('1');
                    value[0] -= 40;
                }
                default -> {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Re-export the key from a trusted source to rule out corruption.
  2. Validate with `openssl asn1parse -inform DER -in key.der` to confirm element types and order.
  3. Convert to PKCS#8 so PemUtils uses a single uniform code path.
  4. If parsing custom DER, re-check the schema and read elements in the correct order/types.

Example fix

// before: parser misaligned, readAsn1Object returns SEQUENCE not OCTET_STRING
DerParser.Asn1Object elem = parser.readAsn1Object(); // unexpectedly a SEQUENCE
String s = elem.getString(); // throws

// after: validate type before reading
if (elem.getType() != DerParser.Type.OCTET_STRING && elem.getType() != DerParser.Type.UTF8_STRING) {
    throw new IOException("unexpected tag 0x" + Integer.toHexString(elem.getType()));
}
String s = elem.getString();
Defensive patterns

Strategy: type-guard

Type guard

private static final Set<Integer> STRING_TYPES = Set.of(
    DerParser.Type.OCTET_STRING, DerParser.Type.NUMERIC_STRING,
    DerParser.Type.PRINTABLE_STRING, DerParser.Type.VIDEOTEX_STRING,
    DerParser.Type.IA5_STRING, DerParser.Type.GRAPHIC_STRING,
    DerParser.Type.ISO646_STRING, DerParser.Type.GENERAL_STRING,
    DerParser.Type.BMP_STRING, DerParser.Type.UTF8_STRING);

public static boolean isStringElement(DerParser.Asn1Object o) {
    return o != null && STRING_TYPES.contains(o.getType());
}

Prevention

When it happens

Trigger: getString() switch hits default. Typical when getString() is called on a SEQUENCE, SET, INTEGER, OID, BOOLEAN, or any other non-string element — most commonly because the parser is misaligned (a previous element was skipped or read with the wrong type).

Common situations: Corrupted or misaligned DER, wrong key format, or a key whose internal layout does not match the expected structure (e.g. an RSA key with extra fields that shifts subsequent reads).

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/bf6ac3f357be9d2f. Report an issue: GitHub.