{"record":{"id":"952567562e8fbad9","repo":"cube-js/cube","slug":"function-registration-must-be-used-with-functions","errorCode":null,"errorMessage":"function registration must be used with functions, actual: '%s'","messagePattern":"function registration must be used with functions, actual: '(.+?)'","errorType":"exception","errorClass":"TemplateException","httpStatus":null,"severity":"error","filePath":"packages/cubejs-backend-native/python/cube/src/__init__.py","lineNumber":181,"sourceCode":"# backward compatibility\nsettings = config\n\nclass TemplateException(Exception):\n    pass\n\nclass TemplateContext:\n    functions: dict[str, Callable]\n    variables: dict[str, Any]\n    filters: dict[str, Callable]\n\n    def __init__(self):\n        self.functions = {}\n        self.variables = {}\n        self.filters = {}\n\n    def add_function(self, name, func):\n        if not callable(func):\n            raise TemplateException(\"function registration must be used with functions, actual: '%s'\" % type(func).__name__)\n\n        self.functions[name] = func\n\n    def add_variable(self, name, val):\n        if name in self.functions:\n            raise TemplateException(\"unable to register variable: name '%s' is already in use for function\" % name)\n\n        self.variables[name] = val\n\n    def add_filter(self, name, func):\n        if not callable(func):\n            raise TemplateException(\"function registration must be used with functions, actual: '%s'\" % type(func).__name__)\n\n        self.filters[name] = func\n\n    def function(self, func):\n        if isinstance(func, str):\n            return TemplateFunctionRef(self, func)","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-backend-native/python/cube/src/__init__.py#L163-L199","documentation":"Cube's Python template module raises TemplateException from add_function() when the value passed as a function is not callable. The registry only stores callables so later template evaluation can invoke them safely.","triggerScenarios":"Calling Template.add_function(name, x) where x is not callable — e.g. a string, dict, None, or the result of forgetting to define the function.","commonSituations":"Typos where the intended function was never defined (NameError avoided by passing a string), passing a lambda-less value, refactoring that replaced a function with a constant.","solutions":["Pass an actual callable: define the function (def or lambda) before registering it.","If you meant a constant value, use add_variable(name, val) instead.","If you registered a string name intending a later lookup, register TemplateFunctionRef or resolve the function first."],"exampleFix":"// before\ntemplate.add_function('upper', 'uppercase')\n// after\ntemplate.add_function('upper', lambda s: s.upper())","handlingStrategy":"validation","validationCode":"if not callable(func):\n    raise TypeError(f\"add_function expects a callable, got {type(func).__name__}\")\ntemplate.add_function(name, func)","typeGuard":"def is_callable_fn(x) -> bool:\n    return callable(x)","tryCatchPattern":"try:\n    template.add_function(name, func)\nexcept TemplateException as e:\n    log.error('bad function registration: %s', e)","preventionTips":["Always define the callable before registering it","Use add_variable for constants instead of add_function","Check callable(x) in dynamic registration loops"],"tags":["python","template","type-error"],"backgroundTag":"invalid-argument-value","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}