{"record":{"id":"858c5d2ef029f498","repo":"apache/druid","slug":"at-most-one-of-s-or-s-must-be-present","errorCode":null,"errorMessage":"At most one of [%s] or [%s] must be present","messagePattern":"At most one of \\[(.+?)\\] or \\[(.+?)\\] must be present","errorType":"validation","errorClass":"IAE","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/indexer/Checks.java","lineNumber":73,"sourceCode":"\n  /**\n   * @return Non-null value, or first one if both are null. -1 is interpreted as null for historical reasons.\n   */\n  public static <T> Property<T> checkAtMostOneNotNull(Property<T> property1, Property<T> property2)\n  {\n    final Property<T> property;\n\n    boolean isNull1 = property1.getValue() == null;\n    boolean isNull2 = property2.getValue() == null;\n\n    if (isNull1 && isNull2) {\n      property = property1;\n    } else if (isNull1) {\n      property = property2;\n    } else if (isNull2) {\n      property = property1;\n    } else {\n      throw new IAE(\"At most one of [%s] or [%s] must be present\", property1, property2);\n    }\n\n    return property;\n  }\n\n  /**\n   * @return Non-null value, or first one if both are null. -1 is interpreted as null for historical reasons.\n   */\n  public static <T> Property<T> checkAtMostOneNotNull(String name1, T value1, String name2, T value2)\n  {\n    Property<T> property1 = new Property<>(name1, value1);\n    Property<T> property2 = new Property<>(name2, value2);\n    return checkAtMostOneNotNull(property1, property2);\n  }\n\n  private Checks()\n  {\n  }","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/indexer/Checks.java#L55-L91","documentation":"Checks.checkAtMostOneNotNull is a config validation helper: given two mutually exclusive properties, it returns the one that is set (or the first if both are null, with -1 treated as null for historical reasons) and throws this IAE only when both are non-null, i.e. the user supplied conflicting values.","triggerScenarios":"Constructing a Hadoop indexing config where two alternative properties (e.g. partitionSpec vs. shardSpec, or two segment-output options) are both supplied.","commonSituations":"Merging spec templates so both the old and new config fields end up set; copying an existing spec and adding a second option without deleting the first.","solutions":["Remove one of the two conflicting properties from the ingestion spec, keeping only the intended one.","Check for duplicated/merged config files that set both properties.","Consult the Hadoop batch task docs for which of the pair is supported for your job type."],"exampleFix":"// before\n\"partitionSpec\": {...},\n\"shardSpec\": {...}\n// after\n\"partitionSpec\": {...}","handlingStrategy":"validation","validationCode":"if (prop1.getValue() != null && prop2.getValue() != null) { throw new IllegalArgumentException(\"Only one of prop1/prop2 may be set\"); }","typeGuard":null,"tryCatchPattern":"try { Checks.checkAtMostOneNotNull(p1, p2); } catch (IAE e) { log.error(\"Conflicting properties: {}\", e.getMessage()); throw e; }","preventionTips":["Check for both fields when copying/merging spec JSON","Document which property supersedes the other","Validate specs before job submission"],"tags":["validation","hadoop-ingestion","mutually-exclusive"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}