langgenius/dify · warning · ValueError
Unsupported query list type.
Error message
Unsupported query list type.
What it means
A Pydantic field_validator error on RosterListQuery.statuses/sources: the field normalizes None/empty-string to [] and accepts a list, but any other type (e.g. a bare string, number, dict) is rejected. The validator runs in mode='before', so it sees the raw query value before Pydantic's default list coercion. Surfaces as a 422 validation error.
Source
Thrown at api/controllers/console/agent/roster.py:205
sort_order: str = Field(default="desc", description="Sort order: asc or desc")
start: str | None = Field(default=None, description="Start date (YYYY-MM-DD HH:MM)")
end: str | None = Field(default=None, description="End date (YYYY-MM-DD HH:MM)")
@field_validator("keyword", "status", "source", "start", "end", mode="before")
@classmethod
def empty_string_to_none(cls, value: str | None) -> str | None:
if value == "":
return None
return value
@field_validator("statuses", "sources", mode="before")
@classmethod
def empty_list_values_to_list(cls, value: object) -> list[str]:
if value in (None, ""):
return []
if isinstance(value, list):
return [str(item).strip() for item in value if str(item).strip()]
raise ValueError("Unsupported query list type.")
@field_validator("sort_by")
@classmethod
def validate_sort_by(cls, value: str) -> str:
normalized = value.strip().lower()
if normalized not in {"created_at", "updated_at"}:
raise ValueError("sort_by must be created_at or updated_at")
return normalized
@field_validator("sort_order")
@classmethod
def validate_sort_order(cls, value: str) -> str:
normalized = value.strip().lower()
if normalized not in {"asc", "desc"}:
raise ValueError("sort_order must be asc or desc")
return normalized
View on GitHub (pinned to ef8544b173)
Solutions
- Send list-valued query params using array encoding: ?statuses=active&statuses=ready (Flask returns a list) or ?statuses[]=active.
- If you only need one value, still pass it as a single-element list, or send an empty string/omit to mean 'no filter'.
- Update the client serializer to always emit list form for statuses and sources.
- Unit-test the client against the OpenAPI schema to catch scalar-vs-list regressions.
Example fix
# before ?statuses=active # after ?statuses=active&statuses=ready # or ?statuses[]=active
Defensive patterns
Strategy: validation
Validate before calling
from typing import Any
def coerce_to_list(value: Any) -> list[str]:
if value in (None, ''):
return []
if isinstance(value, list):
return [str(v).strip() for v in value if str(v).strip()]
raise TypeError('statuses/sources must be a list') Type guard
from typing import Any
def is_list_like_query_value(value: Any) -> bool:
return value is None or value == '' or isinstance(value, list) Prevention
- Encode statuses/sources with repeated params or array form on the client.
- Run client requests through the generated OpenAPI schema validator.
- Avoid hand-building query strings for list params.
When it happens
Trigger: GET /console/agents (roster list) with statuses or sources sent as a non-list scalar, e.g. ?statuses=active (no list encoding) where the client/framework did not wrap it in a list, or ?sources=workflow:abc as a bare string instead of repeated/array form.
Common situations: Client that sends a single value without array encoding (statuses=active vs statuses[]=active or statuses=active&statuses=ready); a malformed query string built by hand; a proxy that collapsed repeated params into a single scalar; version change after the validator tightened to reject scalars.
Related errors
- sort_by must be created_at or updated_at
- sort_order must be asc or desc
- Unsupported tag_ids type.
- Invalid UUID format in tag_ids.
- Unsupported creator_ids type.
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/416ff95bce5b2595.
Report an issue: GitHub.