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

  1. Send actions as a flat JSON array of strings, e.g. ["read","write","execute"]
  2. Filter falsy entries client-side before sending: actions.filter(Boolean)
  3. Lowercase and trim values — the validator normalizes case/whitespace but the type must already be string
  4. 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

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


AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14). Data as JSON: /api/errors/3cd498ee115d336f. Report an issue: GitHub.