apache/druid · error · IllegalStateException

unknown event type [%s]

Error message

unknown event type [%s]

What it means

BloomKFilter.deserialize(ByteBuffer, int) requires a non-null buffer containing the serialized filter. If the buffer is null it throws this IOException immediately before attempting to read. Unlike the other errors in this class this is an IOException, so callers should be prepared for checked exception handling.

Source

Thrown at extensions-contrib/ambari-metrics-emitter/src/main/java/org/apache/druid/emitter/ambari/metrics/AmbariMetricsEmitter.java:144

            log.error(
                "Lost total of [%s] events because of emitter queue is full. Please increase the capacity or/and the consumer frequency",
                countLostEvents.get()
            );
          }
        }
      }
      catch (InterruptedException e) {
        log.error(e, "got interrupted with message [%s]", e.getMessage());
        Thread.currentThread().interrupt();
      }
    } else if (event instanceof AlertEvent) {
      for (Emitter emitter : emitterList) {
        emitter.emit(event);
      }
    } else if (event instanceof SegmentMetadataEvent) {
      // do nothing. Ignore this event type
    } else {
      throw new ISE("unknown event type [%s]", event.getClass());
    }
  }

  @Override
  protected String getCollectorUri(String host)
  {
    return constructTimelineMetricUri(getCollectorProtocol(), host, getCollectorPort());
  }

  @Override
  protected String getCollectorProtocol()
  {
    return config.getProtocol();
  }

  @Override
  protected String getCollectorPort()
  {

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Check for null before calling deserialize and handle the null case explicitly (return null / empty result).
  2. Trace where the buffer comes from and why it is null (missing value, failed fetch) rather than letting deserialize report it.
  3. Wrap the call in try-catch for IOException if null inputs are legitimately possible in your data.

Example fix

// before
BloomKFilter bf = BloomKFilter.deserialize(buffer, position);

// after
BloomKFilter bf = (buffer == null) ? null : BloomKFilter.deserialize(buffer, position);
Defensive patterns

Strategy: type-guard

Validate before calling

if (buffer == null) {
  return null; // or skip this value
}

Type guard

BloomKFilter safeDeserialize(ByteBuffer in, int position) throws IOException {
  return (in != null && in.remaining() > position) ? BloomKFilter.deserialize(in, position) : null;
}

Try / catch

try {
  return BloomKFilter.deserialize(buffer, position);
} catch (IOException e) {
  if (buffer == null || e.getMessage().contains("Input stream is null")) {
    return null; // treat as unknown/missing filter
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling BloomKFilter.deserialize(null, position); passing a buffer variable that was never initialized or that came back null from an upstream lookup (e.g. missing dimension value, null expression result) directly into deserialize.

Common situations: Bloom filter lookup code reading a serialized filter stored in a column/lookup that is absent, so the value is null; deserialization code paths that skipped a null check on their input source; tests passing null to exercise error handling.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/995ff4a387907482. Report an issue: GitHub.