{"record":{"id":"01f1ba1f8812a043","repo":"langchain-ai/deepagents","slug":"rubricmiddleware-grader-state-schema-is-require","errorCode":null,"errorMessage":"RubricMiddleware: `grader_state_schema` is required with `build_grader_state`.","messagePattern":"RubricMiddleware: `grader_state_schema` is required with `build_grader_state`\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/deepagents/deepagents/middleware/rubric.py","lineNumber":581,"sourceCode":"        grader_context_schema: type[Any] | None = None,\n        grader_state_schema: type[AgentState[Any]] | None = None,\n        prepare_messages_for_grader: Callable[[list[AnyMessage]], list[AnyMessage]] | None = None,\n        build_grader_state: Callable[[RubricState, int], Mapping[str, Any]] | None = None,\n        max_iterations: int = 3,\n        on_evaluation: Callable[[RubricEvaluation], None] | None = None,\n    ) -> None:\n        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","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/deepagents/deepagents/middleware/rubric.py#L563-L599","documentation":"RubricMiddleware requires `grader_state_schema` whenever a custom `build_grader_state` callback is provided, because the custom builder is expected to produce state conforming to a schema the grader agent can consume. The pairing is mandatory so the grader's typed state stays consistent; building custom state without declaring its schema is rejected at construction.","triggerScenarios":"RubricMiddleware(model=..., build_grader_state=my_builder) with grader_state_schema left as None.","commonSituations":"Adding a custom grader state builder (extra context fields for the grader) and forgetting the matching TypedDict/pydantic schema; upgrading the library where the pairing became enforced.","solutions":["Pass grader_state_schema=<TypedDict or pydantic model matching what build_grader_state returns>.","If you don't need custom state, remove the build_grader_state argument.","Reuse an existing schema (e.g. RubricState extended) that covers your builder's keys.","Check the docs for the expected schema shape for grader input."],"exampleFix":"// before\nRubricMiddleware(model=model, build_grader_state=build_state)\n// after\nclass MyGraderState(RubricState):\n    extra_context: str\nRubricMiddleware(model=model, build_grader_state=build_state, grader_state_schema=MyGraderState)","handlingStrategy":"validation","validationCode":"if build_grader_state is not None and grader_state_schema is None:\n    raise ValueError(\"build_grader_state requires grader_state_schema\")","typeGuard":"def has_builder_schema(builder: Callable | None, schema: type | None) -> bool:\n    return not (builder is not None and schema is None)","tryCatchPattern":"try:\n    mw = RubricMiddleware(model=model, build_grader_state=b, grader_state_schema=s)\nexcept ValueError as e:\n    if \"grader_state_schema\" in str(e):\n        mw = RubricMiddleware(model=model, grader_state_schema=RubricState)  # drop the builder\n    else:\n        raise","preventionTips":["Provide build_grader_state and grader_state_schema together as a pair in your factory function.","Define the schema TypedDict next to the builder in the same module.","Add a unit test constructing the middleware with your builder.","Check docstrings for required argument pairings."],"tags":["python","validation","constructor","value-error"],"backgroundTag":"missing-required-pairing","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}