langgenius/dify · warning · InvokeRateLimitHttpError

rate_limit_error

rate_limit_error

Error message

Rate Limit Error

What it means

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`.

Source

Thrown at api/controllers/console/datasets/rag_pipeline/rag_pipeline_workflow.py:368

        """
        Run draft workflow
        """
        pipeline = load_rag_pipeline(session, str(pipeline_id))
        args = req_data.model_dump()

        try:
            response = PipelineGenerateService.generate(
                session=session,
                pipeline=pipeline,
                user=current_user,
                args=args,
                invoke_from=InvokeFrom.DEBUGGER,
                streaming=True,
            )

            return helper.compact_generate_response(response)
        except InvokeRateLimitError as ex:
            raise InvokeRateLimitHttpError(ex.description)


@console_ns.route("/rag/pipelines/<uuid:pipeline_id>/workflows/published/run")
class PublishedRagPipelineRunApi(Resource):
    @console_ns.expect(console_ns.models[PublishedWorkflowRunPayload.__name__])
    @console_ns.response(200, "Success", console_ns.models[RagPipelineOpaqueResponse.__name__])
    @setup_required
    @login_required
    @account_initialization_required
    @edit_permission_required
    @rbac_permission_required(RBACResourceScope.DATASET, RBACPermission.DATASET_EDIT)
    @with_current_user
    @with_session
    @model_validate(PublishedWorkflowRunPayload)
    def post(self, req_data: PublishedWorkflowRunPayload, session: Session, current_user: Account, pipeline_id: UUID):
        """
        Run published workflow
        """

View on GitHub (pinned to ef8544b173)

Solutions

  1. Back off and retry with exponential jitter; honor Retry-After if the provider supplies it.
  2. Reduce concurrency of draft runs (serialize debugger invocations).
  3. Upgrade or reconfigure the model provider quota, or switch to a higher-tier key.
  4. Cache draft run results during iterative development to avoid redundant invocations.

Example fix

// before
await post(`${base}/draft/run`, payload)
// after
async function runDraftWithBackoff(payload, retries = 4) {
  for (let i = 0; i < retries; i++) {
    try {
      return await post(`${base}/draft/run`, payload)
    } catch (e) {
      if (e.code !== 'rate_limit_error') throw e
      await sleep(Math.min(1000 * 2 ** i, 8000) + Math.random() * 200)
    }
  }
  throw new Error('draft run rate-limited after retries')
}
Defensive patterns

Strategy: retry

Validate before calling

// serialize debugger runs to stay under the rate limit
const queue = new ConcurrencyQueue({ concurrency: 1, minIntervalMs: 1000 })
await queue.add(() => post(`${base}/draft/run`, payload))

Try / catch

try {
  return await post(`${base}/draft/run`, payload)
} catch (e) {
  if (e.code === 'rate_limit_error') {
    const wait = e.retryAfter ?? Math.min(1000 * 2 ** attempt, 8000)
    await sleep(wait + Math.random() * 200)
    return post(`${base}/draft/run`, payload) // bounded retry
  }
  throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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