apache/beam · error · ValueError
Unable to identify callable from %r
Error message
Unable to identify callable from %r
What it means
load_from_script parses a Python source string to find a callable assigned to a variable (or def) to exec. If no assignment/def line is found after scanning all lines, Beam raises ValueError because there is no callable to extract from the source.
Solutions
- Wrap the expression in an assignment: 'my_callable = lambda x: x*2'
- Or use a def: 'def my_callable(x): return x*2'
- If you already have a callable object, do not serialize via source — pass it directly
Example fix
// before
load_from_script('lambda x: x * 2')
// after
load_from_script('double = lambda x: x * 2') Defensive patterns
Strategy: validation
Validate before calling
def is_valid_callable_source(source: str) -> bool:
import ast
try:
tree = ast.parse(source)
except SyntaxError:
return False
return any(isinstance(n, (ast.Assign, ast.FunctionDef)) for n in tree.body) Try / catch
try:
fn = load_from_script(source)
except ValueError as e:
logging.error('no callable in source: %s', e)
raise Prevention
- Always define callables as 'name = <expr>' or 'def name(...): ...'
- Do not pass bare lambda expressions or import-only strings
- Sanity-check the source parses with ast.parse before submission
When it happens
Trigger: Calling load_from_script(source) or load_from_source(source) with a string containing no top-level assignment or function definition (e.g. only an expression like 'lambda x: x' with no 'name = ' prefix, or only imports).
Common situations: Passing a lambda expression directly instead of 'fn = lambda x: ...'; passing a fully-qualified callable name instead of source code; whitespace/comment-only strings.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- A BigQuery table or a query must be specified
- A cluster_identifier should be Optional[Union[str…
- A context manager constructor (not a fully constructed…
- A has been supplied to the model handler, but the required…
- A pubsub message attribute key must not exceed 256 bytes.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/34b78bc34ef04889.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/utils/python_callable.py:100
if line.strip() and line.strip()[0] != '#'
]
common_indent = min(len(line) - len(line.lstrip()) for line in lines)
lines = [line[common_indent:] for line in lines]
if method_name is None:
for ix, line in reversed(list(enumerate(lines))):
if line[0] != ' ':
if line.startswith('def '):
method_name = line[4:line.index('(')].strip()
elif line.startswith('class '):
method_name = line[5:line.index('(') if '(' in
line else line.index(':')].strip()
else:
method_name = '__python_callable__'
lines[ix] = method_name + ' = ' + line
break
else:
raise ValueError("Unable to identify callable from %r" % source)
# pylint: disable=exec-used
# pylint: disable=ungrouped-imports
import apache_beam as beam
exec_globals = {'beam': beam}
exec('\n'.join(lines), exec_globals)
return exec_globals[method_name]
def default_label(self):
src = self._source.strip()
last_line = src.split('\n')[-1]
if last_line[0] != ' ' and len(last_line) < 72:
return last_line
# Avoid circular import.
from apache_beam.transforms.ptransform import label_from_callable
return label_from_callable(self._callable)
@propertyView on GitHub (pinned to 12126d8942)