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

  1. Refresh the integrations list to read the current disabled state before toggling.
  2. Make the client idempotent and only call 'disable' when the binding is currently enabled.
  3. Change the endpoint to return success when the desired state already holds.
  4. 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

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


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/b86296533c1d3c38. Report an issue: GitHub.