{"record":{"id":"271b2acddda31ab8","repo":"langgenius/dify","slug":"rate-limit-error-271b2a","errorCode":"rate_limit_error","errorMessage":"Rate Limit Error","messagePattern":"Rate Limit Error","errorType":"error_code","errorClass":"InvokeRateLimitHttpError","httpStatus":429,"severity":"warning","filePath":"api/controllers/console/datasets/rag_pipeline/rag_pipeline_workflow.py","lineNumber":368,"sourceCode":"        \"\"\"\n        Run draft workflow\n        \"\"\"\n        pipeline = load_rag_pipeline(session, str(pipeline_id))\n        args = req_data.model_dump()\n\n        try:\n            response = PipelineGenerateService.generate(\n                session=session,\n                pipeline=pipeline,\n                user=current_user,\n                args=args,\n                invoke_from=InvokeFrom.DEBUGGER,\n                streaming=True,\n            )\n\n            return helper.compact_generate_response(response)\n        except InvokeRateLimitError as ex:\n            raise InvokeRateLimitHttpError(ex.description)\n\n\n@console_ns.route(\"/rag/pipelines/<uuid:pipeline_id>/workflows/published/run\")\nclass PublishedRagPipelineRunApi(Resource):\n    @console_ns.expect(console_ns.models[PublishedWorkflowRunPayload.__name__])\n    @console_ns.response(200, \"Success\", console_ns.models[RagPipelineOpaqueResponse.__name__])\n    @setup_required\n    @login_required\n    @account_initialization_required\n    @edit_permission_required\n    @rbac_permission_required(RBACResourceScope.DATASET, RBACPermission.DATASET_EDIT)\n    @with_current_user\n    @with_session\n    @model_validate(PublishedWorkflowRunPayload)\n    def post(self, req_data: PublishedWorkflowRunPayload, session: Session, current_user: Account, pipeline_id: UUID):\n        \"\"\"\n        Run published workflow\n        \"\"\"","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/datasets/rag_pipeline/rag_pipeline_workflow.py#L350-L386","documentation":"Returned (HTTP 429, error_code `rate_limit_error`, 'Rate Limit Error') by POST /rag/pipelines/<pipeline_id>/workflows/draft/run when `PipelineGenerateService.generate` raises `services.errors.llm.InvokeRateLimitError`. This signals that the underlying LLM provider (or Dify's own rate limiter) rejected the request because the tenant/app/user exceeded the configured invocation rate. The controller translates it to the HTTP-layer `InvokeRateLimitError`.","triggerScenarios":"Burst-running draft workflows against a provider with a low TPM/RPM quota; many concurrent debugger runs; a downstream provider returning 429; Dify's own rate-limit middleware tripping on the tenant.","commonSituations":"Tight provider quotas (sandbox, trial keys). Load tests hammering the draft run endpoint. A single user repeatedly testing a chatty workflow. Shared provider key across multiple pipelines.","solutions":["Back off and retry with exponential jitter; honor Retry-After if the provider supplies it.","Reduce concurrency of draft runs (serialize debugger invocations).","Upgrade or reconfigure the model provider quota, or switch to a higher-tier key.","Cache draft run results during iterative development to avoid redundant invocations."],"exampleFix":"// before\nawait post(`${base}/draft/run`, payload)\n// after\nasync function runDraftWithBackoff(payload, retries = 4) {\n  for (let i = 0; i < retries; i++) {\n    try {\n      return await post(`${base}/draft/run`, payload)\n    } catch (e) {\n      if (e.code !== 'rate_limit_error') throw e\n      await sleep(Math.min(1000 * 2 ** i, 8000) + Math.random() * 200)\n    }\n  }\n  throw new Error('draft run rate-limited after retries')\n}","handlingStrategy":"retry","validationCode":"// serialize debugger runs to stay under the rate limit\nconst queue = new ConcurrencyQueue({ concurrency: 1, minIntervalMs: 1000 })\nawait queue.add(() => post(`${base}/draft/run`, payload))","typeGuard":null,"tryCatchPattern":"try {\n  return await post(`${base}/draft/run`, payload)\n} catch (e) {\n  if (e.code === 'rate_limit_error') {\n    const wait = e.retryAfter ?? Math.min(1000 * 2 ** attempt, 8000)\n    await sleep(wait + Math.random() * 200)\n    return post(`${base}/draft/run`, payload) // bounded retry\n  }\n  throw e\n}","preventionTips":["Serialize draft runs during iterative development to avoid bursts.","Cache previous run outputs to skip redundant invocations.","Tune provider quotas to match expected debugger concurrency.","Always retry 429 with exponential backoff and jitter."],"tags":["rag-pipeline","rate-limit","llm-provider","retry","api","rest"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}