{"record":{"id":"a8ffea700654d8ca","repo":"langflow-ai/langflow","slug":"connections-contains-app-id-values-not-referenced","errorCode":null,"errorMessage":"connections contains app_id values not referenced by operations: {unused_raw_app_ids}","messagePattern":"connections contains app_id values not referenced by operations: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":422,"severity":"error","filePath":"src/backend/base/langflow/api/v1/mappers/deployments/watsonx_orchestrate/payloads.py","lineNumber":256,"sourceCode":"    upsert_attr_name: str,\n) -> None:\n    normalized_remove_ids = {str(remove_id).strip() for remove_id in remove_ids if str(remove_id).strip()}\n    normalized_upsert_ids = {\n        str(getattr(operation, upsert_attr_name, \"\")).strip()\n        for operation in upsert_operations\n        if str(getattr(operation, upsert_attr_name, \"\")).strip()\n    }\n    conflicts = sorted(normalized_remove_ids.intersection(normalized_upsert_ids))\n    if conflicts:\n        msg = f\"{remove_label} cannot be combined with upsert for the same id: {conflicts}\"\n        raise ValueError(msg)\n\n\ndef _validate_api_unused_raw_app_ids(*, raw_app_ids: set[str], referenced_app_ids: set[str]) -> None:\n    unused_raw_app_ids = sorted(raw_app_ids.difference(referenced_app_ids))\n    if unused_raw_app_ids:\n        msg = f\"connections contains app_id values not referenced by operations: {unused_raw_app_ids}\"\n        raise ValueError(msg)\n\n\ndef _validate_api_unique_connection_app_ids(*, connections: list[WatsonxApiKeyValueConnectionPayload]) -> None:\n    app_id_counts = Counter(connection.app_id for connection in connections)\n    duplicates = sorted(app_id for app_id, count in app_id_counts.items() if count > 1)\n    if duplicates:\n        msg = f\"connections contains duplicate app_id values: {duplicates}\"\n        raise ValueError(msg)\n\n\nclass WatsonxApiDeploymentUpdatePayload(BaseModel):\n    \"\"\"Watsonx provider_data API contract for deployment update operations.\n\n    All operation fields default to empty lists so LLM-only updates\n    (changing the model without any tool/connection changes) can be\n    expressed without providing operation entries.\n    \"\"\"\n","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/api/v1/mappers/deployments/watsonx_orchestrate/payloads.py#L238-L274","documentation":"API payload validator: every connection declared in provider_data.connections (identified by app_id) must be referenced by at least one operation (add_flows[].app_ids, upsert_tools[].add_app_ids, etc.). Unreferenced connections raise ValueError 'connections contains app_id values not referenced by operations' (422). This keeps the payload explicit — you cannot ship credentials that nothing binds.","triggerScenarios":"POST/PATCH a wxO deployment whose connections[] includes an app_id not used by any add_flows/upsert_flows/upsert_tools operation in the same request.","commonSituations":"Removing a tool's add_app_ids in the UI but leaving its connection in the list; pre-declaring connections 'for later'; editing a previously-valid payload and deleting one add_app_ids reference.","solutions":["Delete the unreferenced entry from connections, or add its app_id back to some operation's add list.","When removing a binding, remove the connection too if nothing else references it.","Compute referenced ids client-side and filter connections to exactly that set before sending."],"exampleFix":"// before\n{\"connections\": [{\"app_id\": \"c1\"}, {\"app_id\": \"c2\"}], \"upsert_tools\": [{\"tool_id\": \"t\", \"add_app_ids\": [\"c1\"]}]}\n// after\n{\"connections\": [{\"app_id\": \"c1\"}], \"upsert_tools\": [{\"tool_id\": \"t\", \"add_app_ids\": [\"c1\"]}]}","handlingStrategy":"validation","validationCode":"referenced = set()\nfor op in provider_data.get(\"add_flows\", []): referenced.update(op.get(\"app_ids\", []))\nfor op in provider_data.get(\"upsert_tools\", []): referenced.update(op.get(\"add_app_ids\", []))\nprovider_data[\"connections\"] = [c for c in provider_data.get(\"connections\", []) if c[\"app_id\"] in referenced]","typeGuard":"def all_connections_referenced(provider_data: dict) -> bool:\n    referenced = {a for op in provider_data.get(\"add_flows\", []) for a in op.get(\"app_ids\", [])}\n    referenced |= {a for op in provider_data.get(\"upsert_tools\", []) for a in op.get(\"add_app_ids\", [])}\n    return all(c[\"app_id\"] in referenced for c in provider_data.get(\"connections\", []))","tryCatchPattern":null,"preventionTips":["Derive connections from the operations that reference them, not the reverse.","When unbinding an app everywhere, also drop its connection entry.","Compute referenced app_ids client-side and filter connections to that set pre-send."],"tags":["watsonx-orchestrate","pydantic","validation","http-422","connections","referential-integrity"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}