{"record":{"id":"68936e5bc05faff6","repo":"langgenius/dify","slug":"data-source-binding-not-found","errorCode":null,"errorMessage":"Data source binding not found.","messagePattern":"Data source binding not found\\.","errorType":"http","errorClass":"NotFound","httpStatus":404,"severity":"error","filePath":"api/controllers/console/datasets/data_source.py","lineNumber":204,"sourceCode":"        return dump_response(DataSourceIntegrateListResponse, {\"data\": integrate_data}), 200\n\n    @setup_required\n    @login_required\n    @account_initialization_required\n    @console_ns.response(200, \"Success\", console_ns.models[SimpleResultResponse.__name__])\n    @with_current_tenant_id\n    @with_session\n    def patch(\n        self, session: Session, current_tenant_id: str, binding_id: UUID, action: Literal[\"enable\", \"disable\"]\n    ) -> tuple[dict[str, str], int]:\n        binding_id_str = str(binding_id)\n        data_source_binding = session.scalar(\n            select(DataSourceOauthBinding).where(\n                DataSourceOauthBinding.id == binding_id_str, DataSourceOauthBinding.tenant_id == current_tenant_id\n            )\n        )\n        if data_source_binding is None:\n            raise NotFound(\"Data source binding not found.\")\n        # enable binding\n        match action:\n            case \"enable\":\n                if data_source_binding.disabled:\n                    data_source_binding.disabled = False\n                    data_source_binding.updated_at = naive_utc_now()\n                else:\n                    raise ValueError(\"Data source is not disabled.\")\n            # disable binding\n            case \"disable\":\n                if not data_source_binding.disabled:\n                    data_source_binding.disabled = True\n                    data_source_binding.updated_at = naive_utc_now()\n                else:\n                    raise ValueError(\"Data source is disabled.\")\n        return {\"result\": \"success\"}, 200\n\n","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/datasets/data_source.py#L186-L222","documentation":"Flask NotFound (HTTP 404) raised at data_source.py:204 in DataSourceApi.patch (PATCH /data-source/integrates/<binding_id>/<action>). The lookup selects DataSourceOauthBinding by both id == binding_id AND tenant_id == current_tenant_id; if no row matches both, the binding 'does not exist' from this tenant's perspective and NotFound is raised before the enable/disable match runs.","triggerScenarios":"PATCH /console/api/data-source/integrates/<binding_id>/enable|disable where binding_id does not exist, belongs to a different tenant, or was deleted. The tenant-scoped query returns None.","commonSituations":"Stale UI showing a binding that was removed; cross-tenant access attempt; UUID typo; or the binding was disabled+hard-deleted by another admin. Tenant scoping means another tenant's binding id is indistinguishable from a nonexistent one.","solutions":["Re-fetch the integrations list via GET /data-source/integrates to obtain current binding ids for this tenant before patching.","Confirm the binding_id UUID is copied exactly (no extra characters) and belongs to the current tenant.","If the binding was deleted, re-authorize the data source to create a new binding and use the new id.","Ensure the request carries the correct tenant context header/session so current_tenant_id matches the binding's owner."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Fetch current bindings for the tenant and confirm the id before patching.\nconst bindings = await fetch('/console/api/data-source/integrates').then(r => r.json());\nif (!bindings.data.some(b => b.id === bindingId)) {\n  throw new Error('binding_id not in this tenant');\n}","typeGuard":"function bindingBelongsToTenant(b: {id: string}, id: string): boolean { return b.id === id; }","tryCatchPattern":"try {\n  await patchBinding(bindingId, action);\n} catch (e) {\n  if (e.status === 404 && /Data source binding not found/i.test(e.message)) { refreshBindings(); }\n  else throw e;\n}","preventionTips":["Always patch using ids from a fresh GET /data-source/integrates response.","Keep the tenant context header consistent with the binding owner.","Disable UI controls for removed bindings after a list refresh."],"tags":["datasets","data-source","not-found","tenant-scoped"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}