langgenius/dify · warning · ValueError

sort_by must be created_at or updated_at

Error message

sort_by must be created_at or updated_at

What it means

A Pydantic field_validator on RosterListQuery.sort_by: the value (trimmed, lowercased) must be one of {created_at, updated_at}. Any other value is rejected with a 422. The validator normalizes case/whitespace first, so ' Updated_At ' is accepted but 'name' or 'createdAt' is not.

Source

Thrown at api/controllers/console/agent/roster.py:212

        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


class AgentStatisticsQuery(BaseModel):
    source: str | None = Field(
        default=None,
        description=(
            "Filter by a structured webapp:<app_id> or workflow:<app_id> source ID. "
            "Legacy invoke sources and exact workflow version/node source IDs remain supported."
        ),

View on GitHub (pinned to ef8544b173)

Solutions

  1. Send ?sort_by=created_at or ?sort_by=updated_at (case-insensitive, trimmed).
  2. Map frontend column keys to the allowed enum before submitting the query.
  3. Omit sort_by to use the default (updated_at).
  4. Update the client's sort field allowlist from the schema.

Example fix

// before
query.sort_by = 'createdAt'
// after
query.sort_by = 'created_at'
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED_SORT_BY = {'created_at', 'updated_at'}

def normalize_sort_by(value: str) -> str:
    norm = (value or '').strip().lower()
    return norm if norm in ALLOWED_SORT_BY else 'updated_at'

Type guard

def is_valid_sort_by(value: str) -> bool:
    return isinstance(value, str) and value.strip().lower() in {'created_at', 'updated_at'}

Prevention

When it happens

Trigger: GET /console/agents with ?sort_by=<anything else>, e.g. ?sort_by=name, ?sort_by=createdAt, ?sort_by=published_at. Common when a generic table component passes the column key verbatim.

Common situations: Frontend table that sends camelCase column keys (createdAt) instead of snake_case; a client built against a different API that allowed other sort fields; typo in the param.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/fe2cb74a1b97b239. Report an issue: GitHub.