{"record":{"id":"85507d0f44c75db0","repo":"rohitg00/ai-engineering-from-scratch","slug":"schema-type-for-location-must-be-a-string-or-non","errorCode":null,"errorMessage":"schema type for {location} must be a string or non-empty string list","messagePattern":"schema type for (.+?) must be a string or non-empty string list","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"certifications/claude/lessons/10-tool-use-and-agentic-loops/code/main.py","lineNumber":116,"sourceCode":"\ndef _integer_bound(schema: dict[str, Any], name: str) -> int | None:\n    if name not in schema:\n        return None\n    value = schema[name]\n    if not isinstance(value, int) or isinstance(value, bool) or value < 0:\n        raise ValueError(f\"schema {name} must be a non-negative integer\")\n    return value\n\n\ndef _validate_schema_value(value: Any, schema: Any, location: str) -> None:\n    if not isinstance(schema, dict):\n        raise ValueError(f\"schema for {location} must be an object\")\n\n    declared_type = schema.get(\"type\")\n    if declared_type is not None:\n        declared_types = declared_type if isinstance(declared_type, list) else [declared_type]\n        if not declared_types or not all(isinstance(item, str) for item in declared_types):\n            raise ValueError(f\"schema type for {location} must be a string or non-empty string list\")\n        if not any(_matches_json_type(value, item) for item in declared_types):\n            expected = \" or \".join(declared_types)\n            raise ValueError(f\"invalid type for {location}: expected {expected}\")\n\n    if \"enum\" in schema:\n        choices = schema[\"enum\"]\n        if not isinstance(choices, list) or not choices:\n            raise ValueError(f\"schema enum for {location} must be a non-empty list\")\n        if value not in choices:\n            raise ValueError(f\"invalid value for {location}: not in enum\")\n\n    if isinstance(value, (int, float)) and not isinstance(value, bool):\n        for keyword, comparison, message in (\n            (\"minimum\", lambda current, bound: current >= bound, \"below minimum\"),\n            (\"maximum\", lambda current, bound: current <= bound, \"above maximum\"),\n            (\"exclusiveMinimum\", lambda current, bound: current > bound, \"at or below exclusive minimum\"),\n            (\"exclusiveMaximum\", lambda current, bound: current < bound, \"at or above exclusive maximum\"),\n        ):","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/rohitg00/ai-engineering-from-scratch/blob/39ea8a1c6d0b61f071226eff7ede4d4105fed820/certifications/claude/lessons/10-tool-use-and-agentic-loops/code/main.py#L98-L134","documentation":"_validate_schema_value raises ValueError(f'schema type for {location} must be a string or non-empty string list') when the 'type' keyword of a (sub)schema is neither a string nor a non-empty list of strings - e.g. an int, bool, None, empty list, or a list containing non-strings. The validator supports scalar types and type arrays and rejects anything else as an authoring error in the schema itself.","triggerScenarios":"Schemas such as {\"type\": 1}, {\"type\": null}, {\"type\": []}, {\"type\": [\"string\", 2]}, or lists containing unsupported entries. Triggered at the root schema and recursively at any properties/items location named in the message.","commonSituations":"Programmatic schema builders inserting computed types that yield None; YAML configs where 'type' is parsed as a non-string; partial refactors from scalar types to type lists leaving empty arrays.","solutions":["Set 'type' to a single supported string or a non-empty list of supported strings.","Read the {location} in the message to find which subschema has the bad type keyword.","Lint generated schemas: assert type fields are str or a non-empty list[str] before use.","When templating schemas, omit the type key rather than writing null."],"exampleFix":"# before\n{\"type\": []}\n# ValueError: schema type for $.x must be a string or non-empty string list\n\n# after\n{\"type\": [\"string\", \"integer\"]}","handlingStrategy":"type-guard","validationCode":"def type_keyword_ok(schema: dict) -> bool:\n    t = schema.get(\"type\")\n    if t is None:\n        return True\n    if isinstance(t, str):\n        return True\n    return isinstance(t, list) and len(t) > 0 and all(isinstance(x, str) for x in t)","typeGuard":"def is_valid_type_keyword(t) -> bool:\n    if isinstance(t, str):\n        return True\n    return isinstance(t, list) and bool(t) and all(isinstance(x, str) for x in t)","tryCatchPattern":"try:\n    validate_tool_input(value, schema)\nexcept ValueError as exc:\n    if \"string or non-empty string list\" in str(exc):\n        raise SchemaError(f\"fix the schema: {exc}\") from exc\n    raise","preventionTips":["Write 'type' as a plain string unless union types are truly needed.","When templating, omit the type key rather than writing null or empty lists.","Unit-test schema construction so computed types never leak non-strings."],"tags":["python","json-schema","validation","type-declaration"],"backgroundTag":"malformed-json-schema","analyzedSha":"39ea8a1c6d0b61f071226eff7ede4d4105fed820","analyzedAt":"2026-08-26T03:13:46.626Z","schemaVersion":2},"datasetVersion":"2026-08-26T07:17:17.940Z"}