elastic/elasticsearch · error · IllegalArgumentException

unable to parse {} [{}]

Error message

unable to parse {} [{}]

What it means

parseIntFromObjectOrString rejects objects that are not null, not a Number, and not a String parseable by Integer.parseInt. The field name ('source port', 'destination port', 'icmp type', 'icmp code') is interpolated, plus the offending object's toString. Thrown from buildFlow for the corresponding flow field.

Source

Thrown at modules/ingest-common/src/main/java/org/elasticsearch/ingest/common/CommunityIdProcessor.java:281

        return new byte[] { (byte) (num >> 8), (byte) num };
    }

    /**
     * Attempts to coerce an object to an integer
     */
    private static int parseIntFromObjectOrString(Object o, String fieldName) {
        if (o == null) {
            return 0;
        } else if (o instanceof Number number) {
            return number.intValue();
        } else if (o instanceof String string) {
            try {
                return Integer.parseInt(string);
            } catch (NumberFormatException e) {
                // fall through to IllegalArgumentException below
            }
        }
        throw new IllegalArgumentException("unable to parse " + fieldName + " [" + o + "]");
    }

    public static final class Factory implements Processor.Factory {

        static final String DEFAULT_SOURCE_IP = "source.ip";
        static final String DEFAULT_SOURCE_PORT = "source.port";
        static final String DEFAULT_DEST_IP = "destination.ip";
        static final String DEFAULT_DEST_PORT = "destination.port";
        static final String DEFAULT_IANA_NUMBER = "network.iana_number";
        static final String DEFAULT_TRANSPORT = "network.transport";
        static final String DEFAULT_ICMP_TYPE = "icmp.type";
        static final String DEFAULT_ICMP_CODE = "icmp.code";
        static final String DEFAULT_TARGET = "network.community_id";

        @Override
        public CommunityIdProcessor create(
            Map<String, Processor.Factory> registry,
            String tag,

View on GitHub (pinned to db6a809a66)

Solutions

  1. Ensure the field is an Integer, Long, or a String containing only ASCII digits (with optional leading '+/-').
  2. Strip any non-digit characters (e.g. 'tcp/443' -> '443') before community_id runs.
  3. If the value is a decimal ('1.5'), convert to integer upstream or accept it cannot represent a port.
  4. Quarantine failures via on_failure.

Example fix

// before — non-numeric port string
//   { "source": { "port": "tcp/443" } }
//
// after — bare integer string (or numeric type)
//   { "source": { "port": "443" } }
Defensive patterns

Strategy: type-guard

Validate before calling

boolean isParsableInt(Object o) {
    if (o == null) return true;            // null is tolerated (resolves to 0)
    if (o instanceof Number) return true;
    if (o instanceof String s) return s.matches("[+-]?\\d+");
    return false;
}

Type guard

static boolean isPortLike(Object o) {
    return o == null || o instanceof Number
        || (o instanceof String s && s.matches("[+-]?\\d+"));
}

Try / catch

{
  "community_id": {
    "on_failure": [
      { "set": { "field": "ingest.error", "value": "community-id-unparseable-int" } },
      { "redirect": { "pipeline": "quarantine" } }
    ]
  }
}

Prevention

When it happens

Trigger: A port or ICMP type/code field that holds a non-numeric value such as a Boolean, a Map/List, or a String like 'abc' or '1.5' (Integer.parseInt rejects decimal notation). Only Integer values are accepted; Long/Float/Double are accepted because they are Number instances and intValue() is used.

Common situations: ECS field mapped as keyword but populated with 'tcp/443' (mixed); upstream enrichment that wrote a Boolean or object into a port field; CSV ingest with quoting artifacts; users assuming the parser accepts decimal port notation.

Understand the failure class

Related errors


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