{"record":{"id":"3d3725ebce11e46a","repo":"apache/druid","slug":"must-define-exactly-one-of-path-or-pathparts","errorCode":null,"errorMessage":"Must define exactly one of 'path' or 'pathParts'","messagePattern":"Must define exactly one of 'path' or 'pathParts'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/virtual/NestedFieldVirtualColumn.java","lineNumber":142,"sourceCode":"\n  private final boolean hasNegativeArrayIndex;\n\n  @JsonCreator\n  public NestedFieldVirtualColumn(\n      @JsonProperty(\"columnName\") String columnName,\n      @JsonProperty(\"outputName\") String outputName,\n      @JsonProperty(\"expectedType\") @Nullable ColumnType expectedType,\n      @JsonProperty(\"pathParts\") @Nullable List<NestedPathPart> parts,\n      @JsonProperty(\"processFromRaw\") @Nullable Boolean processFromRaw,\n      @JsonProperty(\"path\") @Nullable String path,\n      @JsonProperty(\"useJqSyntax\") @Nullable Boolean useJqSyntax\n  )\n  {\n    this.outputName = outputName;\n    if (path != null) {\n      Preconditions.checkArgument(parts == null, \"Cannot define both 'path' and 'pathParts'\");\n    } else if (parts == null) {\n      throw new IllegalArgumentException(\"Must define exactly one of 'path' or 'pathParts'\");\n    }\n    final List<NestedPathPart> pathParts;\n    if (parts != null) {\n      pathParts = parts;\n    } else {\n      boolean isInputJq = useJqSyntax != null && useJqSyntax;\n      pathParts = isInputJq ? NestedPathFinder.parseJqPath(path) : NestedPathFinder.parseJsonPath(path);\n    }\n    boolean hasNegative = false;\n    for (NestedPathPart part : pathParts) {\n      if (part instanceof NestedPathArrayElement) {\n        NestedPathArrayElement elementPart = (NestedPathArrayElement) part;\n        if (elementPart.getIndex() < 0) {\n          hasNegative = true;\n          break;\n        }\n      }\n    }","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/virtual/NestedFieldVirtualColumn.java#L124-L160","documentation":"NestedFieldVirtualColumn extracts a nested field either via a jq-style 'path' string or a pre-parsed list of 'pathParts'; exactly one must be provided. Supplying neither (or the constructor seeing path==null and parts==null) throws IllegalArgumentException so a column with no way to locate the field is never created.","triggerScenarios":"JSON spec for a nested field virtual column with only 'path' removed while 'pathParts' is also absent; programmatic construction passing null for both path and parts.","commonSituations":"Hand-edited virtual column JSON where 'path' was deleted; building the column in Java and forgetting to set either field; deserializing partial specs from older configs.","solutions":["Set exactly one of 'path' (e.g. '$.a.b') or 'pathParts' in the virtual column spec","Construct with NestedFieldVirtualColumn(String column, String outputName, String path, ...) or the parts-based constructor","If both were supplied, remove one — note the related 'Cannot define both' check"],"exampleFix":"// before\n{\"type\":\"nested\",\"column\":\"c\",\"outputName\":\"o\"} // no path/pathParts\n// after\n{\"type\":\"nested\",\"column\":\"c\",\"outputName\":\"o\",\"path\":\"$.a.b\"}","handlingStrategy":"validation","validationCode":"if ((path == null) == (pathParts == null)) {\n  throw new IllegalArgumentException(\"Define exactly one of 'path' or 'pathParts'\");\n}","typeGuard":"boolean wellFormed = (path != null) ^ (pathParts != null);","tryCatchPattern":"try { new NestedFieldVirtualColumn(col, out, path, parts, useJq, null, null, null); } catch (IllegalArgumentException e) { /* repair spec */ }","preventionTips":["Always specify 'path' in JSON specs (simplest) and let pathParts be derived","Validate jq/path syntax before registering the virtual column","Never hand-edit both fields; keep exactly one"],"tags":["virtual-column","nested-fields","validation","config"],"backgroundTag":"missing-required-argument","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"}