apache/beam · error · TypeError
f'Test specification must be an object, got {type(test_spec)
Error message
f'Test specification must be an object, got {type(test_spec)}' What it means
Raised by validate_test_spec when the object passed to a YAML pipeline test is not a mapping (e.g. it was loaded from malformed YAML into a string or list). The validator cannot inspect test attributes like mock_inputs/expected_outputs on a non-dict, so it rejects the whole test_spec before any field checks run. The input at fault is the test_spec argument itself, typically produced by yaml.safe_load of a test file.
Source
Thrown at sdks/python/apache_beam/yaml/yaml_testing.py:142
def _preprocess_for_testing(pipeline_spec):
spec = yaml_transform.pipeline_as_composite(pipeline_spec['pipeline'])
# These are idempotent, so it's OK to do them preemptively.
for phase in [
yaml_transform.ensure_transforms_have_types,
yaml_transform.preprocess_source_sink,
yaml_transform.preprocess_chain,
yaml_transform.tag_explicit_inputs,
yaml_transform.normalize_inputs_outputs,
]:
spec = yaml_transform.apply_phase(phase, spec)
return spec
def validate_test_spec(test_spec):
if not isinstance(test_spec, dict):
raise TypeError(
f'Test specification must be an object, got {type(test_spec)}')
identifier = (
test_spec.get('name', 'unknown') +
f' at line {yaml_transform.SafeLineLoader.get_line(test_spec)}')
if not isinstance(test_spec.get('allowed_sources', []), list):
raise TypeError(
f'allowed_sources of test specification {identifier} '
f'must be a list, got {type(test_spec["allowed_sources"])}')
if (not test_spec.get('expected_outputs', []) and
not test_spec.get('expected_inputs', [])):
raise ValueError(
f'test specification {identifier} '
f'must have at least one expected_outputs or expected_inputs')
unknown_attrs = set(
yaml_transform.SafeLineLoader.strip_metadata(test_spec).keys()) - set([View on GitHub (pinned to 12126d8942)
Solutions
- Make each entry under 'tests:' a mapping with test-spec keys.
- Check YAML indentation so the test object's keys nest under the entry.
- Validate with isinstance(spec, dict) before calling validate_test_spec.
Example fix
# before
tests:
- just_a_name
# after
tests:
- name: just_a_name
expected_outputs:
out: [...] Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(test_spec, dict):
raise TypeError(f'test spec must be a mapping, got {type(test_spec).__name__}') Type guard
def is_test_spec(x) -> bool:
return isinstance(x, dict) and ('expected_outputs' in x or 'expected_inputs' in x) Try / catch
try:
validate_test_spec(test_spec)
except TypeError as e:
logging.error('Malformed test spec: %s', e)
raise Prevention
- Ensure each tests: entry is a YAML mapping
- Check indentation after editing test YAML
- Parse the YAML and inspect types before running tests
When it happens
Trigger: Passing a YAML test entry that is a string or list instead of a mapping with keys like name, expected_outputs, allowed_sources; e.g. 'tests: ["my_test"]'.
Common situations: Malformed YAML indentation turning the test spec into a string, or quoting the whole test object as a scalar.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- f'allowed_sources of test specification {identifier} must be
- At most one of --create_test and --fix_tests may be specifie
- tests attribute must be a list of test specifications.
- f'Non-mocked source {name_or_type} at line {yaml_transform.S
- f'test specification {identifier} must have at least one exp
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/c7e5a4281c17ffd2.
Report an issue: GitHub.