langgenius/dify · warning · ValueError
Data source is disabled.
Error message
Data source is disabled.
What it means
Python ValueError raised at data_source.py:219 in the 'disable' branch of DataSourceApi.patch when the caller sends action=disable but data_source_binding.disabled is already True (binding is already disabled). Symmetric to error 456: disabling an already-disabled binding is rejected. Like 456, it is a bare ValueError rather than a proper HTTP exception, so callers may see an unexpected status.
Source
Thrown at api/controllers/console/datasets/data_source.py:219
)
)
if data_source_binding is None:
raise NotFound("Data source binding not found.")
# enable binding
match action:
case "enable":
if data_source_binding.disabled:
data_source_binding.disabled = False
data_source_binding.updated_at = naive_utc_now()
else:
raise ValueError("Data source is not disabled.")
# disable binding
case "disable":
if not data_source_binding.disabled:
data_source_binding.disabled = True
data_source_binding.updated_at = naive_utc_now()
else:
raise ValueError("Data source is disabled.")
return {"result": "success"}, 200
@console_ns.route("/notion/pre-import/pages")
class DataSourceNotionListApi(Resource):
@setup_required
@login_required
@account_initialization_required
@console_ns.doc(params=query_params_from_model(DataSourceNotionListQuery))
@console_ns.response(200, "Success", console_ns.models[NotionIntegrateInfoListResponse.__name__])
@with_current_user
@with_current_tenant_id
@with_session(write=False)
@model_validate(DataSourceNotionListQuery)
def get(
self,
req_data: DataSourceNotionListQuery,
session: Session,View on GitHub (pinned to ef8544b173)
Solutions
- Refresh the integrations list to read the current disabled state before toggling.
- Make the client idempotent and only call 'disable' when the binding is currently enabled.
- Change the endpoint to return success when the desired state already holds.
- Convert the ValueError to a proper Conflict/BadRequest HTTP exception for a stable client contract.
Example fix
// before (data_source.py:214-219)
case "disable":
if not data_source_binding.disabled:
data_source_binding.disabled = True
data_source_binding.updated_at = naive_utc_now()
else:
raise ValueError("Data source is disabled.")
// after — idempotent disable
case "disable":
if not data_source_binding.disabled:
data_source_binding.disabled = True
data_source_binding.updated_at = naive_utc_now()
# already disabled: no-op Defensive patterns
Strategy: validation
Validate before calling
// Only send 'disable' when the binding is currently enabled.
if (action === 'disable' && binding.disabled === true) {
// already disabled — skip the call
return;
}
await patchBinding(binding.id, 'disable'); Type guard
function shouldDisable(b: {disabled: boolean}): boolean { return b.disabled === false; } Try / catch
try {
await patchBinding(bindingId, 'disable');
} catch (e) {
if (/is disabled/i.test(String(e.message||e))) { /* already disabled, ignore */ return; }
throw e;
} Prevention
- Confirm current disabled state from a fresh fetch before toggling.
- Prevent concurrent toggles from double-firing.
- Advocate for returning a stable HTTP status instead of a bare ValueError.
When it happens
Trigger: PATCH /console/api/data-source/integrates/<binding_id>/disable on a binding whose disabled flag is already True. The else-branch of `if not data_source_binding.disabled` fires.
Common situations: UI shows a binding as enabled while the server already has it disabled; double submit; or a concurrent disable by another admin already completed.
Related errors
- Data source is not disabled.
- Data source binding not found.
- Data source type not support
- Child chunk not found.
- auth_failed
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/b86296533c1d3c38.
Report an issue: GitHub.