apache/druid · error · IllegalArgumentException
Cannot simultaneously replace and append to existing segment
Error message
Cannot simultaneously replace and append to existing segments. Either dropExisting or appendToExisting should be set to false
What it means
Thrown by AbstractTask.computeIngestionMode when both appendToExisting and dropExisting are true, meaning the task asks to both append to and replace (drop) existing segments at once — a logically contradictory ingestion mode. Druid derives IngestionMode from these two flags and refuses the combination.
Source
Thrown at indexing-service/src/main/java/org/apache/druid/indexing/common/task/AbstractTask.java:421
protected static IngestionMode computeBatchIngestionMode(@Nullable BatchIOConfig ioConfig)
{
final boolean isAppendToExisting = ioConfig == null
? BatchIOConfig.DEFAULT_APPEND_EXISTING
: ioConfig.isAppendToExisting();
final boolean isDropExisting = ioConfig == null ? BatchIOConfig.DEFAULT_DROP_EXISTING : ioConfig.isDropExisting();
return computeIngestionMode(isAppendToExisting, isDropExisting);
}
private static IngestionMode computeIngestionMode(boolean isAppendToExisting, boolean isDropExisting)
{
if (!isAppendToExisting && isDropExisting) {
return IngestionMode.REPLACE;
} else if (isAppendToExisting && !isDropExisting) {
return IngestionMode.APPEND;
} else if (!isAppendToExisting) {
return IngestionMode.REPLACE_LEGACY;
}
throw new IAE("Cannot simultaneously replace and append to existing segments. "
+ "Either dropExisting or appendToExisting should be set to false");
}
/**
* Emits a metric for this task using the {@link #getMetricBuilder() metric builder}.
*/
public void emitMetric(
ServiceEmitter emitter,
String metric,
Number value
)
{
if (emitter == null || metric == null || value == null) {
return;
}
emitter.emit(getMetricBuilder().setMetric(metric, value));
}
View on GitHub (pinned to 9b90983fd2)
Solutions
- Set dropExisting=false to append to existing segments, or set appendToExisting=false to replace them — keep exactly one true.
- If replacement is intended (compaction-like behavior), remove appendToExisting from the spec so REPLACE mode is selected.
- If appending is intended, remove dropExisting so APPEND mode is selected.
- Validate the spec before submission with a JSON-schema or pre-submit check on ioConfig flags.
Example fix
// before
"ioConfig": { "type": "index_parallel", "appendToExisting": true },
"tuningConfig": { "dropExisting": true }
// after (append intended)
"ioConfig": { "type": "index_parallel", "appendToExisting": true },
"tuningConfig": { "dropExisting": false } Defensive patterns
Strategy: validation
Validate before calling
final boolean append = ioConfig.isAppendToExisting();
final boolean drop = tuningConfig.isDropExisting();
if (append && drop) throw new IllegalArgumentException("Set at most one of appendToExisting/dropExisting to true"); Try / catch
try { submitTask(spec); } catch (IAE e) { if (e.getMessage().contains("simultaneously replace and append")) { fix flags and resubmit; } else throw e; } Prevention
- Treat dropExisting and appendToExisting as mutually exclusive in spec templates.
- Lint compaction/ingestion specs for both flags true before submission.
- When migrating specs between task types, reset both flags to defaults.
When it happens
Trigger: Submitting an ingestion or compaction task spec (e.g., ParallelIndexTask, BatchTask, CompactionTask) whose tuningConfig/ioConfig sets dropExisting=true while appendToExisting=true; via native JSON specs or SQL-based compaction configs where both flags were flipped on.
Common situations: Copy-pasting a compaction spec with dropExisting=true into an append task without removing appendToExisting; editing task JSON by hand; migration scripts that set both flags to 'true' defensively.
Understand the failure class
Background: "mutually exclusive" flag errors: what "can't supply both nx and xx", "--raw is not compatible with -i" and "cannot be used with" mean, and how to fix them — this error's family across 29 libraries.
Related errors
- Interval[%s] is empty, must specify a nonempty interval
- GranularitySpec's intervals cannot be empty for replace.
- SeekableStreamSupervisorIOConfig does not support both prope
- taskCountMax or taskCountMin can't be null!
- taskCountMax can't lower than taskCountMin!
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/3b53eb9bee64697e.
Report an issue: GitHub.