apache/beam · error · IllegalArgumentException

Failed to instantiate lineage implementation

Error message

Failed to instantiate lineage implementation: %s. The class must have a public constructor accepting (PipelineOptions, Lineage.LineageDirection).

What it means

Beam's Lineage class loads a user-configured lineage implementation class reflectively. createLineage throws IllegalArgumentException when the configured class cannot be instantiated because it lacks a public constructor taking (PipelineOptions, Lineage.LineageDirection).

Solutions

  1. Add or fix a public constructor on the lineage class accepting exactly (PipelineOptions, Lineage.LineageDirection).
  2. Verify the fully-qualified class name configured for lineage is correct and on the classpath.
  3. Make the class public and non-abstract (and its constructor public).
  4. Check the Beam version's Lineage SPI signature if migrating code from an older release.

Example fix

// before
private MyLineage() {}
// after
public MyLineage(PipelineOptions options, Lineage.LineageDirection direction) {
  // init
}
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = Class.forName(lineageClassName); c.getDeclaredConstructor(PipelineOptions.class, Lineage.LineageDirection.class);

Try / catch

try { configureLineage(options); } catch (IllegalArgumentException e) { LOG.error("lineage class invalid: " + e.getMessage(), e); throw e; }

Prevention

When it happens

Trigger: Setting the lineage implementation option (via PipelineOptions) to a class whose constructor signature does not match (PipelineOptions, LineageDirection), is not public, or is abstract/missing.

Common situations: Upgrading Beam where the Lineage SPI contract changed, hand-rolled lineage classes with no-arg constructors, or passing a private nested class without a public constructor.

Related errors


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

Appendix: source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/metrics/Lineage.java:108

    }
    // When no type is requested, preserve whatever is already initialized.
    // When a type is requested, only re-init if it differs from the active type.
    return requestedType == null || requestedType.equals(currentLineageType);
  }

  private static Lineage createLineage(PipelineOptions options, LineageDirection direction) {
    Class<? extends LineageBase> lineageClass = options.as(LineageOptions.class).getLineageType();

    if (lineageClass != null) {
      try {
        LineageBase lineage =
            lineageClass
                .getDeclaredConstructor(PipelineOptions.class, LineageDirection.class)
                .newInstance(options, direction);
        LOG.info("Using {} for lineage direction {}", lineageClass.getName(), direction);
        return new Lineage(lineage);
      } catch (ReflectiveOperationException e) {
        throw new IllegalArgumentException(
            "Failed to instantiate lineage implementation: "
                + lineageClass.getName()
                + ". The class must have a public constructor accepting "
                + "(PipelineOptions, Lineage.LineageDirection).",
            e);
      }
    }

    LOG.debug("Using default Metrics-based lineage for direction {}", direction);
    LineageBase defaultLineage =
        MetricsFlag.lineageRollupEnabled()
            ? new BoundedTrieMetricsLineage(options, direction)
            : new StringSetMetricsLineage(options, direction);
    return new Lineage(defaultLineage);
  }

  /** {@link Lineage} representing sources and optionally side inputs. */
  @SuppressFBWarnings(

View on GitHub (pinned to 12126d8942)