langflow-ai/langflow · warning · ValueError
actions must be strings
Error message
actions must be strings
What it means
Pydantic field-validator error on the /authz/me effective-permissions request body: every element of the actions array must be a Python str. Raising ValueError inside the validator makes Pydantic wrap it into a ValidationError, which FastAPI returns as HTTP 422.
Source
Thrown at src/backend/base/langflow/api/v1/authz_me.py:104
@classmethod
def _normalize_actions(cls, value: list[str] | None) -> list[str] | None:
"""Lowercase, strip, de-duplicate (order-preserving), and cap the actions list.
Returns ``None`` when the caller omitted the field (handler substitutes
``_DEFAULT_ACTIONS``). An empty list after normalization also returns
``None`` so the default kicks in rather than producing an empty cartesian
product downstream.
"""
if value is None:
return None
seen: set[str] = set()
normalized: list[str] = []
for raw in value:
if not isinstance(raw, str):
# Pydantic field_validators must raise ValueError (not TypeError)
# to be wrapped into a ValidationError -> HTTP 422 response.
msg = "actions must be strings"
raise ValueError(msg) # noqa: TRY004
cleaned = raw.strip().lower()
if not cleaned or cleaned in seen:
continue
seen.add(cleaned)
normalized.append(cleaned)
if len(normalized) > _MAX_ACTIONS:
msg = f"actions capped at {_MAX_ACTIONS} unique entries"
raise ValueError(msg)
return normalized or None
class EffectivePermissionsResponse(BaseModel):
"""Response: ``{resource_id: [allowed_actions]}``."""
resource_type: ResourceTypeLiteral
permissions: dict[UUID, list[str]]
View on GitHub (pinned to 976ec789d2)
Solutions
- Send actions as a flat JSON array of strings, e.g. ["read","write","execute"]
- Filter falsy entries client-side before sending: actions.filter(Boolean)
- Lowercase and trim values — the validator normalizes case/whitespace but the type must already be string
- Omit actions entirely to use the default action set
Example fix
// before
body: JSON.stringify({ resource_type: 'flow', resource_ids: ids, actions: [null, 'read'] })
// after
body: JSON.stringify({ resource_type: 'flow', resource_ids: ids, actions: ['read'] }) Defensive patterns
Strategy: type-guard
Validate before calling
const actions = rawActions.filter(a => typeof a === 'string' && a.trim());
Type guard
const isStringArray = (v: unknown): v is string[] => Array.isArray(v) && v.every(x => typeof x === 'string');
Try / catch
catch (e) { if (e.status === 422) showFormErrors(e.errors); } // map pydantic errors to form fields Prevention
- Type the request body in TypeScript so non-strings fail at compile time
- Filter undefined/null out of arrays built from optional variables
- Keep actions as a flat string list — no nested arrays or objects
When it happens
Trigger: POST to the effective-permissions endpoint with actions containing a non-string, e.g. {"actions": [null, 123, true, {}]} or actions sent as a nested array [["read"]] instead of a flat list of strings.
Common situations: JS clients pushing undefined/null entries into the array via array.push(someVar) where someVar is undefined, JSON serializers emitting numbers for action ids, or a schema change where actions was previously an enum/objects list.
Related errors
- actions capped at {_MAX_ACTIONS} unique entries
- String must not be empty.
- credentials contains duplicate key values: {sorted(duplicate
- {label} must not reference connections app_ids: {invalid_raw
- {label} add_app_ids and remove_app_ids must not overlap: {ov
AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14).
Data as JSON: /api/errors/3cd498ee115d336f.
Report an issue: GitHub.