langgenius/dify · warning · InvokeRateLimitHttpError

rate_limit_error

rate_limit_error

Error message

Rate Limit Error

What it means

Raised as InvokeRateLimitHttpError (HTTP 400, code 'rate_limit_error') from the AdvancedChatDraftWorkflowRunApi.post handler at POST /apps/{app_id}/advanced-chat/workflows/draft/run when AppGenerateService.generate triggers the per-tenant/per-app rate limiter during an advanced-chat draft debug run. The underlying core.error.InvokeRateLimitError carries a description string that is forwarded verbatim to the HTTP error. It signals the debug-run invocation exceeded the configured invocation quota, not a model provider 429.

Source

Thrown at api/controllers/console/app/workflow.py:730

            args["external_trace_id"] = external_trace_id

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

            return helper.compact_generate_response(response)
        except services.errors.conversation.ConversationNotExistsError:
            raise NotFound("Conversation Not Exists.")
        except services.errors.conversation.ConversationCompletedError:
            raise ConversationCompletedError()
        except InvokeRateLimitError as ex:
            raise InvokeRateLimitHttpError(ex.description)
        except ValueError as e:
            raise e
        except Exception:
            logger.exception("internal server error.")
            raise InternalServerError()


@console_ns.route("/apps/<uuid:app_id>/advanced-chat/workflows/draft/iteration/nodes/<string:node_id>/run")
class AdvancedChatDraftRunIterationNodeApi(Resource):
    @console_ns.doc("run_advanced_chat_draft_iteration_node")
    @console_ns.doc(description="Run draft workflow iteration node for advanced chat")
    @console_ns.doc(params={"app_id": "Application ID", "node_id": "Node ID"})
    @console_ns.expect(console_ns.models[IterationNodeRunPayload.__name__])
    @console_ns.response(
        200,
        "Iteration node run started successfully",
        console_ns.models[GeneratedAppResponse.__name__],
    )

View on GitHub (pinned to ef8544b173)

Solutions

  1. Back off and retry the same draft run after the limiter window elapses; the response description states the wait.
  2. Check the rate-limit configuration for the workspace/tenant and raise the cap if the legitimate debug load needs it.
  3. Stop duplicate concurrent run requests from the client (debounce the run button, cancel in-flight requests).
  4. Inspect server logs to confirm the limiter key (tenant/app/user) and identify which caller is saturating it.

Example fix

// before: client retries immediately on any error
async function runDraft() {
  await fetch(`/apps/${appId}/advanced-chat/workflows/draft/run`, {method:'POST', body});
}
// after: honor Retry-After / back off on rate_limit_error
async function runDraft() {
  const r = await fetch(url, {method:'POST', body});
  if (r.status === 400 && (await r.json()).code === 'rate_limit_error') {
    await sleep(backoffMs()); return;
  }
}
Defensive patterns

Strategy: retry

Validate before calling

// Before the call, gate on a client-side token bucket sized to the known workspace limit.
const bucket = makeTokenBucket({capacity: RATE_LIMIT, refillPerSec: REFILL});
async function safeDraftRun(appId, body) {
  if (!bucket.tryConsume(1)) {
    return {skip: true, retryInMs: bucket.timeUntilNext()};
  }
  return fetch(`/console/apps/${appId}/advanced-chat/workflows/draft/run`, {method:'POST', body: JSON.stringify(body)});
}

Try / catch

// Honor the rate-limit description / back off; surface to UI as throttled.
try {
  return await runDraftRun(appId, body);
} catch (e) {
  if (isHttpError(e, 400, 'rate_limit_error')) {
    scheduleRetry(e.description); // parse wait from description
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Issuing repeated POST /apps/{app_id}/advanced-chat/workflows/draft/run (streaming debugger) faster than the workspace's rate-limit window allows; the limiter trips inside AppGenerateService.generate before the SSE stream is returned.

Common situations: Auto-retry loops in the workflow debugger, a stuck frontend re-firing the run on error, shared dev tenant hammered by several developers, or rate-limit config (e.g. dify_config invocation quotas) set too low for the workload.

Related errors


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