apache/druid · error · IllegalStateException

A batch appenderator was already created for this peon's…

Error message

A batch appenderator was already created for this peon's task.

What it means

createRealtimeAppenderatorForTask throws this ISE when a batch appenderator has already been created for this peon. A peon can host either a realtime or a batch appenderator, but never both, since the manager holds single fields for each.

Solutions

  1. Do not mix batch and realtime appenderator creation in one peon; pick one per task
  2. Create a separate task for the batch portion of the workload
  3. Refactor custom task code so the ingestion type is decided once before any appenderator is created

Example fix

// before
manager.createBatchAppenderatorForTask(...);
manager.createRealtimeAppenderatorForTask(...); // throws
// after
if (isBatch) {
  manager.createBatchAppenderatorForTask(...);
} else {
  manager.createRealtimeAppenderatorForTask(...);
}
Defensive patterns

Strategy: validation

Validate before calling

if (peonManager.batchAppenderatorExists()) throw new IllegalStateException("batch appenderator already present");

Type guard

boolean canCreateRealtime = !manager.hasBatchAppenderator();

Try / catch

try { manager.createRealtimeAppenderatorForTask(...); } catch (ISE e) { log.error("cannot mix batch and realtime appenderators", e); throw e; }

Prevention

When it happens

Trigger: A task first created a batch appenderator via createBatchAppenderatorForTask and then attempts to create a realtime appenderator in the same peon process.

Common situations: Mixing batch and streaming ingestion logic in one custom task; misconfigured task type causing the wrong creation path to be invoked twice.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at server/src/main/java/org/apache/druid/segment/realtime/appenderator/PeonAppenderatorsManager.java:95

      QueryRunnerFactoryConglomerate conglomerate,
      DataSegmentAnnouncer segmentAnnouncer,
      ServiceEmitter emitter,
      QueryProcessingPool queryProcessingPool,
      JoinableFactory joinableFactory,
      Cache cache,
      CacheConfig cacheConfig,
      CachePopulatorStats cachePopulatorStats,
      PolicyEnforcer policyEnforcer,
      RowIngestionMeters rowIngestionMeters,
      ParseExceptionHandler parseExceptionHandler,
      CentralizedDatasourceSchemaConfig centralizedDatasourceSchemaConfig,
      TaskIntervalUnlocker taskIntervalUnlocker
  )
  {
    if (realtimeAppenderator != null) {
      throw new ISE("A realtime appenderator was already created for this peon's task.");
    } else if (batchAppenderator != null) {
      throw new ISE("A batch appenderator was already created for this peon's task.");
    } else {
      realtimeAppenderator = Appenderators.createRealtime(
          segmentLoaderConfig,
          taskId,
          schema,
          config,
          metrics,
          dataSegmentPusher,
          jsonMapper,
          indexIO,
          indexMerger,
          conglomerate,
          segmentAnnouncer,
          emitter,
          queryProcessingPool,
          cache,
          cacheConfig,
          cachePopulatorStats,

View on GitHub (pinned to 9b90983fd2)