apache/beam · error

Unknown timing constant: " + timing

Error message

Unknown timing constant: " + timing

What it means

ExternalTransform.to_runner_api_transform raises RuntimeError when translating an expanded external transform to its runner API form and more than one input tag was renamed (not present in the expanded transform's inputs). With non-preserved tags there is no way to map original tags to expanded tags unambiguously once two renames are seen, so the translation aborts. This is an internal consistency check during pipeline serialization.

Source

Thrown at sdks/typescript/src/apache_beam/coders/required_coders.ts:544

          "Timing number 0b" +
            timingNumber.toString(2) +
            " has more than two bits of info",
        );
    }
  }

  private static encodeTiming(timing: Timing): number {
    switch (timing) {
      case Timing.EARLY:
        return 0b00;
      case Timing.ON_TIME:
        return 0b01;
      case Timing.LATE:
        return 0b10;
      case Timing.UNKNOWN:
        return 0b11;
      default:
        throw new Error("Unknown timing constant: " + timing);
    }
  }

  private static chooseEncoding(value: PaneInfo): number {
    if (
      (value.index === 0 && value.onTimeIndex === 0) ||
      value.timing === Timing.UNKNOWN
    ) {
      return PaneInfoEncoding.NO_INDEX;
    } else if (
      value.index === value.onTimeIndex ||
      value.timing === Timing.EARLY
    ) {
      return PaneInfoEncoding.ONE_INDEX;
    } else {
      return PaneInfoEncoding.TWO_INDICES;
    }
  }

View on GitHub (pinned to 12126d8942)

Solutions

  1. Ensure input tags match the expanded transform's tags; do not rename inputs of an external transform after expansion.
  2. Upgrade/downgrade apache-beam so the Python SDK and the expansion service jar agree on tag naming.
  3. Report/inspect the two key sets in the message to identify which transform's tags drifted.

Example fix

// before
p | 'label' >> ExternalTransform(...).with_inputs({'wrong_tag': pcoll})
// after
p | 'label' >> ExternalTransform(...).with_inputs({'expected_tag': pcoll})  # match expanded tags
Defensive patterns

Strategy: try-catch

Validate before calling

assert set(t._inputs).issubset(set(t._expanded_transform.inputs)) or len(t._inputs) == 1

Type guard

def tags_preserved(local_inputs: dict, expanded_inputs: dict) -> bool:
    return set(local_inputs) == set(expanded_inputs)

Try / catch

try:
    run_pipeline(pipeline)
except RuntimeError as e:
    if 'non-preserved tags' in str(e):
        logger.error('External transform input tags drifted; align SDK and jar versions: %s', e)
    raise

Prevention

When it happens

Trigger: Applying an ExternalTransform whose expanded counterpart has a single input while the applied transform has multiple local input tags not matching the expanded tags, causing repeated single-input remapping; typically with multi-input external transforms whose tags were not preserved across expansion.

Common situations: Cross-language transforms where the Java expansion renamed/normalized input tags; manually constructed ExternalTransform objects with arbitrary tags; Beam version mismatch causing tag schema changes between SDK and expansion service.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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