{"record":{"id":"6a6baeaefb71ad7e","repo":"langchain-ai/deepagents","slug":"goal-criteria-request-field-key-must-be-text","errorCode":null,"errorMessage":"Goal criteria request field {key} must be text.","messagePattern":"Goal criteria request field (.+?) must be text\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/goal_rubric.py","lineNumber":1238,"sourceCode":"        raise ValueError(msg)\n    if kind not in {\"create\", \"amend\"}:\n        msg = \"Goal criteria request kind must be create or amend.\"\n        raise ValueError(msg)\n    if not isinstance(objective, str) or not objective.strip():\n        msg = \"Goal criteria request requires an objective.\"\n        raise ValueError(msg)\n\n    # Values are validated for non-blankness but stored verbatim (not stripped):\n    # this feature deliberately preserves the user's exact goal/criteria wording,\n    # and the prompt builders wrap each value in explicit XML boundaries.\n    optional: dict[str, str] = {}\n    for key in (\"criteria\", \"feedback\", \"previous_criteria\"):\n        item = value.get(key)\n        if item is None:\n            continue\n        if not isinstance(item, str):\n            msg = f\"Goal criteria request field {key} must be text.\"\n            raise TypeError(msg)\n        optional[key] = item\n\n    if kind == \"amend\":\n        criteria = optional.get(\"criteria\", \"\")\n        feedback = optional.get(\"feedback\", \"\")\n        if not criteria.strip() or not feedback.strip():\n            msg = \"Goal amendment requests require criteria and feedback.\"\n            raise ValueError(msg)\n        return GoalAmendRequest(\n            request_id=request_id,\n            objective=objective,\n            kind=\"amend\",\n            criteria=criteria,\n            feedback=feedback,\n        )\n\n    create: GoalCreateRequest = {\n        \"request_id\": request_id,","sourceCodeStart":1220,"sourceCodeEnd":1256,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/goal_rubric.py#L1220-L1256","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Convert the value to a string before building the request (e.g. `json.dumps(...)` or `\"\\n\".join(items)`).","Remove the key entirely instead of passing a non-string placeholder like `0` or `[]` — `None`/absent is the only allowed 'not provided' representation.","Add a type check in the caller that serializes structured criteria into plain text."],"exampleFix":"// before\nrequest = {\"request_id\": rid, \"kind\": \"amend\", \"objective\": obj, \"criteria\": [\"fast\", \"correct\"]}\n// after\nrequest = {\"request_id\": rid, \"kind\": \"amend\", \"objective\": obj, \"criteria\": \"\\n\".join([\"fast\", \"correct\"])}","handlingStrategy":"type-guard","validationCode":"for key in (\"criteria\", \"feedback\", \"previous_criteria\"):\n    item = value.get(key)\n    if item is not None and not isinstance(item, str):\n        raise TypeError(f\"{key} must be a string, got {type(item).__name__}\")","typeGuard":"def optional_text(value: dict, key: str) -> bool:\n    item = value.get(key)\n    return item is None or isinstance(item, str)","tryCatchPattern":"try:\n    run_middleware(state)\nexcept TypeError as e:\n    if \"must be text\" in str(e):\n        coerce_structured_fields_to_text(state[\"goal_request\"])","preventionTips":["Serialize structured criteria (lists/dicts) to text with `json.dumps` or `\"\\n\".join` before building the request.","Use `None` (or omit the key) to mean 'not provided'; never pass empty containers.","Type-annotate the request builder with `dict[str, str | None]` to catch this at check time."],"tags":["validation","typeerror","type-mismatch"],"backgroundTag":"schema-validation-failed","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}