{"record":{"id":"4113fdc4905b3db2","repo":"langflow-ai/langflow","slug":"credentials-contains-duplicate-key-values-sorted","errorCode":null,"errorMessage":"credentials contains duplicate key values: {sorted(duplicates)}","messagePattern":"credentials contains duplicate key values: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":422,"severity":"error","filePath":"src/backend/base/langflow/api/v1/mappers/deployments/watsonx_orchestrate/payloads.py","lineNumber":198,"sourceCode":"    credentials: list[WatsonxApiConnectionCredentialItem] | None = None\n\n    @field_validator(\"credentials\")\n    @classmethod\n    def validate_unique_credential_keys(\n        cls,\n        value: list[WatsonxApiConnectionCredentialItem] | None,\n    ) -> list[WatsonxApiConnectionCredentialItem] | None:\n        if value is None:\n            return None\n        seen: set[str] = set()\n        duplicates: set[str] = set()\n        for item in value:\n            if item.key in seen:\n                duplicates.add(item.key)\n            seen.add(item.key)\n        if duplicates:\n            msg = f\"credentials contains duplicate key values: {sorted(duplicates)}\"\n            raise ValueError(msg)\n        return value\n\n\ndef _collect_api_referenced_app_ids(operations: list[Any], *, attr_name: str = \"app_ids\") -> set[str]:\n    referenced_app_ids: set[str] = set()\n    for operation in operations:\n        operation_app_ids = getattr(operation, attr_name, None)\n        if not operation_app_ids:\n            continue\n        referenced_app_ids.update(operation_app_ids)\n    return referenced_app_ids\n\n\ndef _validate_api_remove_not_raw(*, operations: list[Any], raw_app_ids: set[str], attr_name: str, label: str) -> None:\n    for operation in operations:\n        remove_app_ids = getattr(operation, attr_name, None)\n        if not remove_app_ids:\n            continue","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/api/v1/mappers/deployments/watsonx_orchestrate/payloads.py#L180-L216","documentation":"Model validator on the wxO connection credentials payload: within provider_data.connections[].credentials (list of {key, ...} items), each key must be unique. The validator collects duplicates and raises ValueError 'credentials contains duplicate key values: [..]', which FastAPI returns as 422 during request validation.","triggerScenarios":"POST/PATCH a wxO deployment with a connections[] entry whose credentials list contains two or more items with the same key (e.g. two 'API_KEY' entries with different values for different environments).","commonSituations":"Merging credential lists from multiple environments into one connection; copy-paste editing of credentials arrays; generator code appending per-env credentials without deduplication.","solutions":["Deduplicate credentials by key within each connection — one entry per key.","If you need the same key for different environments, put them in separate connections entries (each with its own app_id) rather than one credentials list.","Validate client-side: assert len({c['key'] for c in creds}) == len(creds) before sending."],"exampleFix":"// before\n{\"app_id\": \"app1\", \"credentials\": [{\"key\": \"API_KEY\", \"value\": \"a\"}, {\"key\": \"API_KEY\", \"value\": \"b\"}]}\n// after\n{\"app_id\": \"app1\", \"credentials\": [{\"key\": \"API_KEY\", \"value\": \"a\"}], }\n// or split into two connections with distinct app_ids","handlingStrategy":"validation","validationCode":"keys = [c[\"key\"] for c in connection[\"credentials\"]]\nif len(keys) != len(set(keys)):\n    raise ValueError(f\"duplicate credential keys: {sorted({k for k in keys if keys.count(k) > 1})}\")","typeGuard":"def has_unique_credential_keys(credentials: list[dict]) -> bool:\n    keys = [c[\"key\"] for c in credentials]\n    return len(keys) == len(set(keys))","tryCatchPattern":"try:\n    await api.post(\"/deployments\", body)\nexcept ValidationError as e:  # FastAPI 422 body\n    dup_msgs = [d for d in e.errors() if \"duplicate key values\" in d[\"msg\"]]\n    if dup_msgs:\n        dedupe_credentials_by_last_write(body)","preventionTips":["One credential entry per key per connection.","Use separate connections (distinct app_ids) for per-environment credentials.","Deduplicate credentials client-side before every submit."],"tags":["watsonx-orchestrate","pydantic","validation","http-422","credentials","duplicates"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}