apache/beam · error · ValueError
change_function must be 'CHANGES' or 'APPENDS', got '{change
Error message
change_function must be 'CHANGES' or 'APPENDS', got '{change_function}' What it means
ReadBigQueryChangeHistory only supports the BigQuery change-history functions 'CHANGES' and 'APPENDS'. Any other change_function string is rejected in __init__ with a ValueError that echoes the invalid value, because the generated change-history query syntax depends on this enum.
Source
Thrown at sdks/python/apache_beam/io/gcp/bigquery_change_history.py:1214
change_type_column: str = 'change_type',
change_timestamp_column: str = 'change_timestamp',
columns: Optional[list[str]] = None,
row_filter: Optional[str] = None,
batch_arrow_read: bool = True,
max_split_rounds: int = 1,
reshuffle_decompress: bool = True) -> None:
super().__init__()
if bq_storage is None:
raise ImportError(
'google-cloud-bigquery-storage is required for '
'ReadBigQueryChangeHistory. Install it with: '
'pip install google-cloud-bigquery-storage')
if pyarrow is None:
raise ImportError(
'pyarrow is required for ReadBigQueryChangeHistory. '
'Install it with: pip install pyarrow')
if change_function not in ('CHANGES', 'APPENDS'):
raise ValueError(
f"change_function must be 'CHANGES' or 'APPENDS', "
f"got '{change_function}'")
if poll_interval_sec < 15:
raise ValueError(
f'poll_interval_sec must be >= 15, got {poll_interval_sec}')
if buffer_sec < 0:
raise ValueError(f'buffer_sec must be >= 0, got {buffer_sec}')
self._table = table
self._poll_interval_sec = poll_interval_sec
self._start_time = start_time
self._stop_time = stop_time
self._change_function = change_function
self._buffer_sec = buffer_sec
self._project = project
self._temp_dataset = temp_dataset
self._location = location
self._change_type_column = change_type_column
self._change_timestamp_column = change_timestamp_columnView on GitHub (pinned to 12126d8942)
Solutions
- Set change_function='CHANGES' for row-level change history.
- Set change_function='APPENDS' for append-only tables.
- Use the exact uppercase spelling; the check is case-sensitive.
Example fix
// before ReadFromBigQueryChangeHistory(..., change_function="changes") // after ReadFromBigQueryChangeHistory(..., change_function="CHANGES")
Defensive patterns
Strategy: validation
Validate before calling
assert change_function in ("CHANGES", "APPENDS"), \
f"change_function must be 'CHANGES' or 'APPENDS', got {change_function!r}" Type guard
from typing import Literal ChangeFunction = Literal["CHANGES", "APPENDS"]
Try / catch
try:
transform = ReadFromBigQueryChangeHistory(..., change_function=fn)
except ValueError as e:
log.error("invalid change_function: %s", e) Prevention
- Use the exact uppercase strings 'CHANGES' or 'APPENDS'
- Type the parameter as Literal['CHANGES','APPENDS'] in calling code
- Watch for casing when the value originates from config files or CLI flags
When it happens
Trigger: Passing change_function='CHANGE' (singular), 'changes' (lowercase), 'INSERTUPDATEDELETE', or any other string outside ('CHANGES', 'APPENDS') when constructing ReadFromBigQueryChangeHistory.
Common situations: Typos or wrong casing when specifying the change function; confusing this option with BigQuery CDC terms like 'MERGE'; copying examples for different APIs.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Invalid create disposition %s. Expecting %s
- Invalid write disposition %s. Expecting %s
- Invalid schema update option %s. Expecting %s
- poll_interval_sec must be >= 15, got {poll_interval_sec}
- buffer_sec must be >= 0, got {buffer_sec}
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/0da200c881e2c39e.
Report an issue: GitHub.