apache/beam · error · ValueError

Only one of read_artifact_location or…

Error message

Only one of read_artifact_location or write_artifact_location can be specified to initialize MLTransform

What it means

MLTransform is initialized in either produce (write artifacts) or consume (read artifacts) mode, never both. Passing both read_artifact_location and write_artifact_location is ambiguous, so a ValueError is raised.

Solutions

  1. Keep only one of the two: write_artifact_location to produce artifacts, read_artifact_location to consume them.
  2. If chaining transforms that both write and read, split into separate MLTransform steps in the pipeline.

Example fix

// before
MLTransform(read_artifact_location=read_dir, write_artifact_location=write_dir, transforms=[...])
// after
MLTransform(write_artifact_location=write_dir, transforms=[...])
Defensive patterns

Strategy: validation

Validate before calling

def make_mltransform(**kw):
    if kw.get('read_artifact_location') and kw.get('write_artifact_location'):
        raise ValueError('Pass only one artifact location')
    return MLTransform(**kw)

Type guard

def artifact_mode_ok(read_loc, write_loc) -> bool:
    return bool(read_loc) != bool(write_loc)

Try / catch

try:
    t = MLTransform(read_artifact_location=r, write_artifact_location=w, transforms=ts)
except ValueError as e:
    if 'Only one of' in str(e):
        t = MLTransform(write_artifact_location=w, transforms=ts)
    else:
        raise

Prevention

When it happens

Trigger: Calling MLTransform(read_artifact_location=..., write_artifact_location=...) with both locations set.

Common situations: Refactoring a write-mode pipeline to read-mode and leaving the old write_artifact_location argument in place; copy-pasting between training and inference pipeline examples.

Related errors


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

Appendix: source

Thrown at sdks/python/apache_beam/ml/transforms/base.py:355

        overwrite any artifacts already in this location, so distinct locations
        should be used for each instance of MLTransform. Only one of
        write_artifact_location and read_artifact_location should be specified.
      read_artifact_location: A storage location to read artifacts resulting
        froma previous MLTransform. These artifacts include transformations
        applied to the dataset and generated values like min, max from
        ScaleTo01, and mean, var from ScaleToZScore. Note that when consuming
        artifacts, it is not necessary to pass the transforms since they are
        inherently stored within the artifacts themselves. The value assigned
        to `read_artifact_location` should be a valid storage path where the
        artifacts can be read from. Only one of write_artifact_location and
        read_artifact_location should be specified.
      transforms: A list of transforms to apply to the data. All the transforms
        are applied in the order they are specified. The input of the
        i-th transform is the output of the (i-1)-th transform. Multi-input
        transforms are not supported yet.
    """
    if read_artifact_location and write_artifact_location:
      raise ValueError(
          'Only one of read_artifact_location or write_artifact_location can '
          'be specified to initialize MLTransform')

    if not read_artifact_location and not write_artifact_location:
      raise ValueError(
          'Either a read_artifact_location or write_artifact_location must be '
          'specified to initialize MLTransform')

    if read_artifact_location:
      artifact_location = read_artifact_location
      artifact_mode = ArtifactMode.CONSUME
      if transforms:
        raise ValueError(
            'Transforms should not be passed in read mode. In read mode, '
            'the transforms are read from the artifact location.')

    else:
      artifact_location = write_artifact_location  # type: ignore[assignment]

View on GitHub (pinned to 12126d8942)