{"record":{"id":"478e21ca8920bbd4","repo":"apache/beam","slug":"cannot-specify-callable-with-path-and-name-for-function","errorCode":null,"errorMessage":"\"Cannot specify 'callable' with 'path' and 'name' for function.\"","messagePattern":"\"Cannot specify 'callable' with 'path' and 'name' for function\\.\"","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/yaml/yaml_specifiable.py","lineNumber":34,"sourceCode":"#\n\nfrom apache_beam.io.filesystems import FileSystems\nfrom apache_beam.ml.anomaly.specifiable import Spec\nfrom apache_beam.ml.anomaly.transforms import AnomalyDetection\nfrom apache_beam.ml.anomaly.transforms import Specifiable\nfrom apache_beam.utils import python_callable\nfrom apache_beam.yaml.yaml_provider import InlineProvider\n\n\ndef maybe_make_specifiable(v):\n  if isinstance(v, dict):\n    if \"type\" in v and \"config\" in v:\n      return Specifiable.from_spec(\n          Spec(type=v[\"type\"], config=maybe_make_specifiable(v[\"config\"])))\n\n    if \"callable\" in v:\n      if \"path\" in v or \"name\" in v:\n        raise ValueError(\n            \"Cannot specify 'callable' with 'path' and 'name' for function.\")\n      else:\n        return python_callable.PythonCallableWithSource(v[\"callable\"])\n\n    if \"path\" in v and \"name\" in v:\n      return python_callable.PythonCallableWithSource.load_from_script(\n          FileSystems.open(v[\"path\"]).read().decode(), v[\"name\"])\n\n    ret = {k: maybe_make_specifiable(v[k]) for k in v}\n    return ret\n  else:\n    return v\n\n\nclass SpecProvider(InlineProvider):\n  def create_transform(self, type, args, yaml_create_transform):\n    return self._transform_factories[type](\n        **{","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/yaml/yaml_specifiable.py#L16-L52","documentation":"maybe_make_specifiable converts YAML values into callable/Specifiable objects. A value containing 'callable' specifies an inline Python callable; 'path'+'name' specifies loading from a script. These two forms are mutually exclusive, so specifying 'callable' together with 'path' or 'name' raises a ValueError.","triggerScenarios":"Passing a dict like {'callable': 'lambda x: x', 'path': 'my_mod.py'} or {'callable': ..., 'name': 'my_func'} to a specifiable field (e.g. a map's fn or a filter's language expression argument).","commonSituations":"Users paste an inline callable into a config that was previously script-based, or leave stale 'path'/'name' keys behind when inlining the function.","solutions":["Remove 'path' and 'name' keys when providing an inline 'callable'.","Remove 'callable' and keep only 'path' and 'name' to load from a script.","Split the config so exactly one specification form remains."],"exampleFix":"# before\nfn:\n  callable: 'lambda x: x + 1'\n  path: my_funcs.py\n  name: increment\n\n# after\nfn:\n  callable: 'lambda x: x + 1'","handlingStrategy":"validation","validationCode":"if isinstance(v, dict) and 'callable' in v and ('path' in v or 'name' in v):\n    raise ValueError('Use either callable or path+name, not both')","typeGuard":"def is_valid_callable_spec(v: dict) -> bool:\n    has_callable = 'callable' in v\n    has_script = 'path' in v and 'name' in v\n    return has_callable != has_script","tryCatchPattern":"try:\n    fn = maybe_make_specifiable(v)\nexcept ValueError as e:\n    logging.error('Specifiable config conflict: %s', e)\n    raise","preventionTips":["Choose one form: inline callable OR script path+name","Remove leftover keys when converting between forms","Validate specifiable dicts before submitting pipelines"],"tags":["python","apache-beam","yaml","config"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}