apache/beam · error · IllegalArgumentException

Column delimiter should be set if headers are present.

Error message

Column delimiter should be set if headers are present.

What it means

DLPDeidentifyText.Builder.build validates paired CSV-style options: if headerColumns are supplied but columnDelimiter is not, the delimiter needed to parse/handle the table is missing, so build throws IllegalArgumentException.

Solutions

  1. Add .setColumnDelimiter(",") (or the delimiter your data uses) alongside setHeaderColumns.
  2. Or remove setHeaderColumns if the data is not columnar.
  3. Default the delimiter in pipeline options when headers are provided.

Example fix

// before
.setHeaderColumns(ImmutableList.of("name","ssn"))
.build();
// after
.setHeaderColumns(ImmutableList.of("name","ssn"))
.setColumnDelimiter(",")
.build();
Defensive patterns

Strategy: validation

Validate before calling

if (headerColumns != null && columnDelimiter == null) throw new IllegalArgumentException("columnDelimiter required with headerColumns");

Prevention

When it happens

Trigger: Calling .setHeaderColumns(...) without calling .setColumnDelimiter(...) before build().

Common situations: Partially porting configuration from another transform; assuming a default delimiter is applied when headers are set; incremental edits to builder code.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/44ff8f3de2d84127. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/extensions/ml/src/main/java/org/apache/beam/sdk/extensions/ml/DLPDeidentifyText.java:174

    abstract DLPDeidentifyText autoBuild();

    public DLPDeidentifyText build() {
      DLPDeidentifyText dlpDeidentifyText = autoBuild();
      if (dlpDeidentifyText.getDeidentifyConfig() == null
          && dlpDeidentifyText.getDeidentifyTemplateName() == null) {
        throw new IllegalArgumentException(
            "Either deidentifyConfig or deidentifyTemplateName need to be set!");
      }
      if (dlpDeidentifyText.getBatchSizeBytes() > DLP_PAYLOAD_LIMIT_BYTES) {
        throw new IllegalArgumentException(
            String.format(
                "Batch size is too large! It should be smaller or equal than %d.",
                DLP_PAYLOAD_LIMIT_BYTES));
      }
      if (dlpDeidentifyText.getColumnDelimiter() == null
          && dlpDeidentifyText.getHeaderColumns() != null) {
        throw new IllegalArgumentException(
            "Column delimiter should be set if headers are present.");
      }
      if (dlpDeidentifyText.getHeaderColumns() == null
          && dlpDeidentifyText.getColumnDelimiter() != null) {
        throw new IllegalArgumentException(
            "Column headers should be supplied when delimiter is present.");
      }
      return dlpDeidentifyText;
    }
  }

  public static DLPDeidentifyText.Builder newBuilder() {
    return new AutoValue_DLPDeidentifyText.Builder();
  }

  /**
   * The transform converts the contents of input PCollection into {@link Table.Row}s and then calls
   * Cloud DLP service to perform the deidentification according to provided settings.

View on GitHub (pinned to 12126d8942)