{"record":{"id":"d316b8bc82af50f5","repo":"apache/beam","slug":"config-for-transform-at-s-must-be-a-mapping","errorCode":null,"errorMessage":"Config for transform at %s must be a mapping.","messagePattern":"Config for transform at (.+?) must be a mapping\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/yaml/yaml_transform.py","lineNumber":390,"sourceCode":"      raise ValueError(\n          'Unknown transform type %r at %s' %\n          (spec['type'], identify_object(spec)))\n\n    # TODO(yaml): Perhaps we can do better than a greedy choice here.\n    # TODO(yaml): Figure out why this is needed.\n    providers_by_input = {k: v for k, v in self.input_providers.items()}\n    input_providers = [\n        providers_by_input[pcoll] for pcoll in input_pcolls\n        if pcoll in providers_by_input\n    ]\n    provider = self.best_provider(spec, input_providers)\n    extra_dependencies, spec = extract_extra_dependencies(spec)\n    if extra_dependencies:\n      provider = provider.with_extra_dependencies(frozenset(extra_dependencies))\n\n    config = SafeLineLoader.strip_metadata(spec.get('config', {}))\n    if not isinstance(config, dict):\n      raise ValueError(\n          'Config for transform at %s must be a mapping.' %\n          identify_object(spec))\n\n    if (not input_pcolls and not is_explicitly_empty(spec.get('input', {})) and\n        provider.requires_inputs(spec['type'], config)):\n      raise ValueError(\n          f'Missing inputs for transform at {identify_object(spec)}')\n\n    try:\n      if spec['type'].endswith('-generic'):\n        # Centralize the validation rather than require every implementation\n        # to do it.\n        validate_generic_expressions(\n            spec['type'].rsplit('-', 1)[0], config, input_pcolls)\n\n      # pylint: disable=undefined-loop-variable\n      ptransform = maybe_with_resource_hints(\n          provider.create_transform(","sourceCodeStart":372,"sourceCodeEnd":408,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/yaml/yaml_transform.py#L372-L408","documentation":"create_ptransform reads `spec['config']` and strips line metadata; the result must be a dict/mapping because it is passed as keyword-style options to the transform. A scalar, list, or string config raises this ValueError naming the spec location.","triggerScenarios":"Writing `config: some_string`, `config: [a, b]`, or a bare value in the YAML instead of a mapping of option names to values; programmatic specs passing a non-dict `config`.","commonSituations":"Config written in flow style that parses as a list; forgetting config contents should be indented key/value pairs; converting from JSON where config was an array; `config: value` instead of `config: {option: value}`.","solutions":["Rewrite the config as a mapping: each option as `key: value` under `config:`.","Check the transform's documented config schema for exact option names.","For a single option, use inline mapping syntax `config: {option: value}`.","Inspect the reported location to confirm the YAML node parses as a dict."],"exampleFix":"# before\n- type: ReadFromBigQuery\n  config: my-project:dataset.table\n# after\n- type: ReadFromBigQuery\n  config:\n    query: 'SELECT * FROM `my-project.dataset.table`'","handlingStrategy":"type-guard","validationCode":"cfg = spec.get('config', {})\nif not isinstance(cfg, dict):\n    raise ValueError(f'config for {spec.get(\"name\")} must be a mapping, got {type(cfg).__name__}')","typeGuard":"def has_mapping_config(spec):\n    return isinstance(spec, dict) and isinstance(spec.get('config', {}), dict)","tryCatchPattern":"try:\n    run_pipeline(spec)\nexcept ValueError as e:\n    if 'must be a mapping' in str(e):\n        raise UserPipelineError('Rewrite config as indented key/value mapping') from e","preventionTips":["Always indent config options under config:","Use flow style config: {k: v} for single options","Validate YAML node types with a schema linter"],"tags":["yaml","beam-yaml","pipeline-definition","type-mismatch"],"backgroundTag":"config-type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}