langflow-ai/langflow · error · ValueError

{label} must not reference connections app_ids: {invalid_raw

Error message

{label} must not reference connections app_ids: {invalid_raw}

What it means

API payload validator for wxO deployment updates: remove_app_ids on upsert_flows/upsert_tools items reference provider tool app bindings, not raw connection app_ids declared in provider_data.connections. If a remove_app_ids value intersects the connections' app_id set, ValueError '{label} must not reference connections app_ids' is raised (surfaces as 422). Removing a connection is expressed via the connections list itself, not via tool operations.

Source

Thrown at src/backend/base/langflow/api/v1/mappers/deployments/watsonx_orchestrate/payloads.py:220

def _collect_api_referenced_app_ids(operations: list[Any], *, attr_name: str = "app_ids") -> set[str]:
    referenced_app_ids: set[str] = set()
    for operation in operations:
        operation_app_ids = getattr(operation, attr_name, None)
        if not operation_app_ids:
            continue
        referenced_app_ids.update(operation_app_ids)
    return referenced_app_ids


def _validate_api_remove_not_raw(*, operations: list[Any], raw_app_ids: set[str], attr_name: str, label: str) -> None:
    for operation in operations:
        remove_app_ids = getattr(operation, attr_name, None)
        if not remove_app_ids:
            continue
        invalid_raw = sorted(raw_app_ids.intersection(set(remove_app_ids)))
        if invalid_raw:
            msg = f"{label} must not reference connections app_ids: {invalid_raw}"
            raise ValueError(msg)


def _validate_api_add_remove_overlap(*, operations: list[Any], label: str) -> None:
    for operation in operations:
        add_app_ids = set(getattr(operation, "add_app_ids", []) or [])
        remove_app_ids = set(getattr(operation, "remove_app_ids", []) or [])
        overlap = sorted(add_app_ids.intersection(remove_app_ids))
        if overlap:
            msg = f"{label} add_app_ids and remove_app_ids must not overlap: {overlap}"
            raise ValueError(msg)


def _validate_api_remove_conflicts(
    *,
    remove_ids: list[Any],
    upsert_operations: list[Any],
    remove_label: str,
    upsert_attr_name: str,

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Remove the connection by dropping its entry from provider_data.connections instead of listing its app_id in remove_app_ids.
  2. Keep remove_app_ids limited to provider tool-binding app ids previously added via add_app_ids.
  3. Audit client code so connection ids and tool-binding app ids never share values.

Example fix

// before
{"connections": [{"app_id": "conn1", ...}], "upsert_tools": [{"tool_id": "t1", "remove_app_ids": ["conn1"]}]}
// after
{"connections": [], "upsert_tools": [{"tool_id": "t1", "remove_app_ids": ["<tool-binding-app-id>"]}]}
Defensive patterns

Strategy: validation

Validate before calling

raw_conn_ids = {c["app_id"] for c in provider_data.get("connections", [])}
for item in provider_data.get("upsert_flows", []) + provider_data.get("upsert_tools", []):
    bad = set(item.get("remove_app_ids", [])) & raw_conn_ids
    assert not bad, f"remove_app_ids must not reference connections app_ids: {bad}"

Type guard

def removes_reference_connections(item: dict, conn_ids: set[str]) -> bool:
    return bool(set(item.get("remove_app_ids", [])) & conn_ids)

Prevention

When it happens

Trigger: PATCH a wxO deployment where upsert_flows[i].remove_app_ids or upsert_tools[i].remove_app_ids contains an app_id that also appears in provider_data.connections[].app_id.

Common situations: Developers assuming remove_app_ids can detach a credential connection; UI 'remove' action mistakenly feeding connection ids into tool operations; reusing one id namespace for both connections and tool bindings.

Related errors


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