langchain-ai/deepagents · error · TypeError

Goal criteria request field {key} must be text.

Error message

Goal criteria request field {key} must be text.

What it means

The optional goal-criteria request fields `criteria`, `feedback`, and `previous_criteria` may be omitted (`None`) but, if present, must be strings. `_goal_criteria_request` raises this `TypeError` when one of these keys holds a non-string value (number, list, dict, bool).

Source

Thrown at libs/code/deepagents_code/goal_rubric.py:1238

        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"):
        item = value.get(key)
        if item is None:
            continue
        if not isinstance(item, str):
            msg = f"Goal criteria request field {key} must be text."
            raise TypeError(msg)
        optional[key] = item

    if kind == "amend":
        criteria = optional.get("criteria", "")
        feedback = optional.get("feedback", "")
        if not criteria.strip() or not feedback.strip():
            msg = "Goal amendment requests require criteria and feedback."
            raise ValueError(msg)
        return GoalAmendRequest(
            request_id=request_id,
            objective=objective,
            kind="amend",
            criteria=criteria,
            feedback=feedback,
        )

    create: GoalCreateRequest = {
        "request_id": request_id,

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Convert the value to a string before building the request (e.g. `json.dumps(...)` or `"\n".join(items)`).
  2. Remove the key entirely instead of passing a non-string placeholder like `0` or `[]` — `None`/absent is the only allowed 'not provided' representation.
  3. Add a type check in the caller that serializes structured criteria into plain text.

Example fix

// before
request = {"request_id": rid, "kind": "amend", "objective": obj, "criteria": ["fast", "correct"]}
// after
request = {"request_id": rid, "kind": "amend", "objective": obj, "criteria": "\n".join(["fast", "correct"])}
Defensive patterns

Strategy: type-guard

Validate before calling

for key in ("criteria", "feedback", "previous_criteria"):
    item = value.get(key)
    if item is not None and not isinstance(item, str):
        raise TypeError(f"{key} must be a string, got {type(item).__name__}")

Type guard

def optional_text(value: dict, key: str) -> bool:
    item = value.get(key)
    return item is None or isinstance(item, str)

Try / catch

try:
    run_middleware(state)
except TypeError as e:
    if "must be text" in str(e):
        coerce_structured_fields_to_text(state["goal_request"])

Prevention

When it happens

Trigger: Passing structured/JSON-shaped criteria or feedback (e.g. a list of criterion objects) or a numeric value in one of `criteria`, `feedback`, `previous_criteria` when building the request.

Common situations: Clients serializing criteria as JSON arrays instead of joined text; a config file where feedback was parsed as YAML/JSON into a structure; type drift after refactoring a builder function.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/6a6baeaefb71ad7e. Report an issue: GitHub.