langchain-ai/deepagents · error · TypeError
Goal criteria request must be an object.
Error message
Goal criteria request must be an object.
What it means
`_goal_criteria_request` (a hook used by `before_agent`/`abefore_agent`) parses an incoming goal-criteria request payload and raises `TypeError` if the payload is not a `dict`. It then further validates `request_id`, `kind`, and `objective`, raising `ValueError` for missing/invalid required fields. This guards the tool/hook boundary against malformed requests.
Source
Thrown at libs/code/deepagents_code/goal_rubric.py:1214
summary = summary[:_CRITERIA_RESULT_LOG_LIMIT] + "..."
return summary
def _goal_criteria_request(value: object) -> GoalCriteriaRequest:
"""Validate a goal-criteria request from graph input.
Returns:
A normalized typed request: a `GoalAmendRequest` when `kind` is amend
(with `criteria` and `feedback` guaranteed present), otherwise a
`GoalCreateRequest`. Fields not valid for the resolved kind are dropped.
Raises:
TypeError: If the request or one of its fields has the wrong type.
ValueError: If a required request value is missing or invalid.
"""
if not isinstance(value, dict):
msg = "Goal criteria request must be an object."
raise TypeError(msg)
request_id = value.get("request_id")
kind = value.get("kind")
objective = value.get("objective")
if not isinstance(request_id, str) or not request_id.strip():
msg = "Goal criteria request requires a request_id."
raise ValueError(msg)
if kind not in {"create", "amend"}:
msg = "Goal criteria request kind must be create or amend."
raise ValueError(msg)
if not isinstance(objective, str) or not objective.strip():
msg = "Goal criteria request requires an objective."
raise ValueError(msg)
# Values are validated for non-blankness but stored verbatim (not stripped):
# this feature deliberately preserves the user's exact goal/criteria wording,
# and the prompt builders wrap each value in explicit XML boundaries.
optional: dict[str, str] = {}
for key in ("criteria", "feedback", "previous_criteria"):View on GitHub (pinned to a1af029e6e)
Solutions
- Send the request as a JSON object with string `request_id`, valid `kind`, and non-empty `objective`
- If receiving a JSON string, `json.loads` it before handing it to the hook
- Validate the payload shape at the client boundary before invoking the agent
Example fix
// before
await hook.before_agent(state, request='{"request_id": "r1", ...}')
// after
import json
payload = request if isinstance(request, dict) else json.loads(request)
await hook.before_agent(state, payload) Defensive patterns
Strategy: type-guard
Validate before calling
def validate_request(value) -> dict:
if not isinstance(value, dict):
raise TypeError("Goal criteria request must be an object.")
if not isinstance(value.get("request_id"), str) or not value["request_id"].strip():
raise ValueError("request_id required")
return value Type guard
def is_criteria_request(v: object) -> bool:
return (
isinstance(v, dict)
and isinstance(v.get("request_id"), str)
and bool(v["request_id"].strip())
and isinstance(v.get("objective"), str)
and bool(v["objective"].strip())
) Try / catch
try:
validated = _goal_criteria_request(payload)
except TypeError as exc:
logger.error("payload not an object: %s", exc)
except ValueError as exc:
logger.error("invalid request field: %s", exc) Prevention
- json.loads string payloads before passing them to hooks
- Keep client and hook request schemas in sync; validate at the boundary
- Never pass None or lists where an object is expected
When it happens
Trigger: A before-agent hook receives a request value that is a JSON string, list, or None instead of an object — e.g. the client sent `"{...}"` as a string, an array of fields, or omitted the payload entirely.
Common situations: Tool clients double-encoding JSON so the object arrives as a string; schema drift between caller and hook (field renamed/moved); programmatic callers passing the wrong structure; agent state containing a list of requests instead of a single request object.
Related errors
- interpreter_ptc must be False, 'safe', 'all', or a list of t
- model_retries must be an int, got {self.model_retries!r}
- cli_max_retries must be None or an int, got {self.cli_max_re
- Server '{server_name}' '{field_name}' must be a list of stri
- 'mcpServers' field must be a dictionary
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/da28adbece97f985.
Report an issue: GitHub.