langchain-ai/deepagents · error · ValueError
Goal criteria request kind must be create or amend.
Error message
Goal criteria request kind must be create or amend.
What it means
A goal-criteria request must declare whether it creates a new goal or amends an existing one. `_goal_criteria_request` validates `kind` against the closed set `{"create", "amend"}` and raises this `ValueError` for any other value.
Source
Thrown at libs/code/deepagents_code/goal_rubric.py:1223
(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"):
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":View on GitHub (pinned to a1af029e6e)
Solutions
- Set `kind` to exactly "create" or "amend" (lowercase).
- Normalize caller-side values with `.lower()` before constructing the request.
- Update any custom builder/serializer that emits legacy kind names to the current two-value vocabulary.
Example fix
// before
request = {"request_id": rid, "kind": "Update", "objective": obj}
// after
request = {"request_id": rid, "kind": "amend", "objective": obj} Defensive patterns
Strategy: validation
Validate before calling
kind = value.get("kind")
if kind not in {"create", "amend"}:
raise ValueError(f"kind must be 'create' or 'amend', got {kind!r}") Type guard
from typing import Literal, TypeGuard
GoalKind = Literal["create", "amend"]
def is_valid_kind(kind: object) -> TypeGuard[GoalKind]:
return kind in ("create", "amend") Try / catch
try:
run_middleware(state)
except ValueError as e:
if "kind must be create or amend" in str(e):
log_and_surface_to_user(e) Prevention
- Define a `Literal["create", "amend"]` type or enum for kind and use it everywhere.
- Normalize casing with `.lower()` at the input boundary.
- Keep a single mapping from UI actions to request kinds.
When it happens
Trigger: Supplying `kind` values such as "update", "Create", "new", `None`, or omitting `kind` entirely when building a goal-criteria request that reaches the `before_agent`/`abefore_agent` middleware hook.
Common situations: Case-sensitivity mistakes ("Amend" vs "amend"); renaming a caller-side enum without matching this vocabulary; a code path that reuses a create-request template for a different operation.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Could not parse embedded resource block. Block expected eith
- question text must not be blank
- choice has a blank 'value': {choice!r}
- {question_type} question {question_text!r} requires a non-em
- {question_type} question {question_text!r} must not define '
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/3656361becbcf8cd.
Report an issue: GitHub.