apache/beam · error · ValueError

"Invalid windowing time unit ' '. Valid time units are .

Error message

"Invalid windowing {} time unit '{}'. Valid time units are {}."

What it means

Raised by YamlProviders.WindowInto._parse_duration when the time-unit suffix parsed from a windowing value is not one of the recognized units (the keys of time_units, e.g. s/m/h/d style units). The numeric part parsed fine, but the unit is unknown so the duration cannot be computed.

Solutions

  1. Use a supported unit suffix exactly as listed in the error message (e.g. s, m, h, d style keys).
  2. Omit the suffix entirely to get the default of seconds ('5' means 5 seconds).
  3. Convert manually, e.g. '5min' -> '300s' or '2weeks' -> '14d'.

Example fix

# before
gap: 5min
# after
gap: 300s
Defensive patterns

Strategy: validation

Validate before calling

VALID_UNITS = {'s', 'm', 'h', 'd'}
def validate_duration(v):
    m = re.fullmatch(r'\s*(\d+(?:\.\d+)?)\s*([a-zA-Z]*)\s*', str(v))
    if not m:
        raise ValueError(f'Invalid duration {v!r}')
    unit = m.group(2) or 's'
    if unit not in VALID_UNITS:
        raise ValueError(f'Unit {unit!r} not in {sorted(VALID_UNITS)}')

Type guard

def has_supported_unit(v, units=('s','m','h','d')):
    m = re.match(r'^\d+(?:\.\d+)?([^\d]*)$', str(v).strip())
    return bool(m) and (m.group(1) in units or m.group(1) == '')

Try / catch

try:
    gap = YamlProviders.WindowInto._parse_duration(spec['gap'], 'gap')
except ValueError as e:
    if 'time unit' in str(e):
        logging.warning('Unsupported unit, defaulting to seconds: %s', e)
        gap = float(re.match(r'^(.*?)', str(spec['gap'])).group(1))
    else:
        raise

Prevention

When it happens

Trigger: Passing a windowing duration/gap/offset with an unrecognized unit suffix, e.g. 'gap: 5min', 'gap: 2weeks', 'offset: 10sec' where only 's','m','h','d'-style keys are accepted.

Common situations: YAML authors assume full Python timedelta-style units ('min', 'secs', 'weeks') or misspell a unit; defaults are seconds when no suffix is given.

Understand the failure class

Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.

Related errors


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

Appendix: source

Thrown at sdks/python/apache_beam/yaml/yaml_provider.py:1135

    def expand(self, pcoll):
      return pcoll | self._window_transform

    @staticmethod
    def _parse_duration(value, name):
      time_units = {
          'ms': 0.001, 's': 1, 'm': 60, 'h': 60 * 60, 'd': 60 * 60 * 12
      }
      value, suffix = re.match(r'^(.*?)([^\d]*)$', str(value)).groups()
      # Default to seconds if time unit suffix is not defined
      if not suffix:
        suffix = 's'
      if not value:
        raise ValueError(
            f"Invalid windowing {name} value "
            f"'{suffix if not value else value}'. "
            f"Must provide numeric value.")
      if suffix not in time_units:
        raise ValueError((
            "Invalid windowing {} time unit '{}'. " +
            "Valid time units are {}.").format(
                name,
                suffix,
                ', '.join("'{}'".format(k) for k in time_units.keys())))
      return float(value) * time_units[suffix]

    @staticmethod
    def _parse_window_spec(spec):
      spec = dict(spec)
      window_type = spec.pop('type')
      # TODO: These are in seconds, perhaps parse duration strings meaningfully?
      if window_type == 'global':
        window_fn = window.GlobalWindows()
      elif window_type == 'fixed':
        window_fn = window.FixedWindows(
            YamlProviders.WindowInto._parse_duration(spec.pop('size'), 'size'),
            YamlProviders.WindowInto._parse_duration(

View on GitHub (pinned to 12126d8942)