{"record":{"id":"5fccc01631749cbe","repo":"langchain-ai/deepagents","slug":"rubricmiddleware-name-must-be-callable","errorCode":null,"errorMessage":"RubricMiddleware: `{name}` must be callable.","messagePattern":"RubricMiddleware: `(.+?)` must be callable\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/deepagents/deepagents/middleware/rubric.py","lineNumber":588,"sourceCode":"        if not model:\n            msg = \"RubricMiddleware: `model` is required.\"\n            raise ValueError(msg)\n        if not isinstance(max_iterations, int) or isinstance(max_iterations, bool):\n            msg = f\"RubricMiddleware: `max_iterations` must be an int, got {type(max_iterations).__name__}.\"\n            raise TypeError(msg)\n        if max_iterations < 1:\n            msg = f\"RubricMiddleware: `max_iterations` must be positive, got {max_iterations}.\"\n            raise ValueError(msg)\n        if grader_state_schema is None and build_grader_state is not None:\n            msg = \"RubricMiddleware: `grader_state_schema` is required with `build_grader_state`.\"\n            raise ValueError(msg)\n        for name, callback in (\n            (\"prepare_messages_for_grader\", prepare_messages_for_grader),\n            (\"build_grader_state\", build_grader_state),\n        ):\n            if callback is not None and not callable(callback):\n                msg = f\"RubricMiddleware: `{name}` must be callable.\"\n                raise TypeError(msg)\n\n        self.max_iterations = max_iterations\n        self._model = model\n        self._model_label = _configured_model_label(model)\n        self._system_prompt = system_prompt or GRADER_SYSTEM_PROMPT\n        self._tools: list[BaseTool] = list(tools) if tools else []\n        self._grader_middleware = grader_middleware or ()\n        self._grader_context_schema = grader_context_schema\n        self._grader_state_schema = grader_state_schema\n        self._prepare_messages_for_grader = prepare_messages_for_grader\n        self._build_grader_state = build_grader_state\n        self._on_evaluation = on_evaluation\n        # Built lazily so importing the middleware doesn't construct a model\n        # client (which can trigger env-var lookups / API key validation).\n        self._grader: Any = None\n        self._resolved_model: BaseChatModel | None = None\n\n    def before_agent(","sourceCodeStart":570,"sourceCodeEnd":606,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/deepagents/deepagents/middleware/rubric.py#L570-L606","documentation":"The optional hooks `prepare_messages_for_grader` and `build_grader_state` must be callable if provided. Passing a non-callable (e.g. a class instance, dict, or string) is rejected with TypeError at construction since the middleware invokes them as functions.","triggerScenarios":"RubricMiddleware(model=..., prepare_messages_for_grader=my_dict) or build_grader_state=SomeClass (an uninstantiated/decorated object that isn't callable) or the result of a call like build_grader_state=make_builder() where make_builder returns non-callable data.","commonSituations":"Assigning the wrong variable from a config; calling the factory instead of passing the factory; forgetting a decorator like @staticmethod/@functools.wraps so the attribute isn't callable; JSON-deserialized config where functions became strings.","solutions":["Pass the function itself, not its result: build_grader_state=build_state, not build_grader_state=build_state().","Verify with callable(fn) before constructing.","If using a method, bind it (self.method) and confirm it's a bound method.","Check for accidental shadowing of the function name by data."],"exampleFix":"// before\nRubricMiddleware(model=model, build_grader_state=make_builder())\n// after\nRubricMiddleware(model=model, build_grader_state=make_builder()(3) if callable_needed else build_state)","handlingStrategy":"type-guard","validationCode":"hooks = {\"prepare_messages_for_grader\": prep, \"build_grader_state\": build}\nfor name, fn in hooks.items():\n    if fn is not None and not callable(fn):\n        raise TypeError(f\"{name} must be callable, got {type(fn).__name__}\")","typeGuard":"def is_callback(v: object) -> TypeGuard[Callable]:\n    return v is None or callable(v)","tryCatchPattern":"try:\n    mw = RubricMiddleware(model=model, build_grader_state=build)\nexcept TypeError as e:\n    if \"must be callable\" in str(e):\n        mw = RubricMiddleware(model=model)  # drop the bad hook\n    else:\n        raise","preventionTips":["Pass the function object, not the result of calling it.","Guard config-loaded hooks with callable(fn).","Watch for names shadowed by data (e.g. a dict named build_grader_state).","Remember None is allowed; anything non-callable and non-None is not."],"tags":["python","validation","constructor","type-error"],"backgroundTag":"invalid-parameter-type","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}