instructure/canvas-lms · warning · RateLimited

Cedar rate limit exceeded for #

Error message

Cedar rate limit exceeded for #{tool_key}: #{e.message}

What it means

call_cedar invokes the Cedar client (InstructureMiscPlugin::Extensions::CedarClient). When Cedar itself reports its CedarLimitReachedError, the service logs a warning tagged with tool_key and converts it to the service-level RateLimited error. This is distinct from the InstLLMHelper limit (error 1100) — this is the upstream Cedar-side cap.

Solutions

  1. Check Cedar-side quota/limits for the environment and raise them if artificially low
  2. Confirm the feature_slug study-assist-#{tool_key} isn't double-emitting events (e.g., retry loops calling call_cedar repeatedly)
  3. Add backoff/retry with jitter on the caller side for RateLimited originating from Cedar
  4. Verify CedarClient configuration (endpoint, credentials, account) matches the intended environment

Example fix

// before
cedar_client.record(event) # CedarLimitReachedError -> RateLimited
// after
begin
  cedar_client.record(event)
rescue InstructureMiscPlugin::Extensions::CedarClient::CedarLimitReachedError
  Rails.logger.info('cedar limit reached, dropping event')
end
Defensive patterns

Strategy: try-catch

Try / catch

begin
  service.call_cedar(tool_key, llm_config, content)
rescue StudyAssist::RateLimited => e
  metrics.increment('study_assist.cedar_limited', tags: { tool: tool_key })
  # drop or defer the Cedar event
end

Prevention

When it happens

Trigger: call -> call_cedar hits Cedar's event/ingestion quota: CedarLimitReachedError is raised by CedarClient while recording analytics events for the study-assist feature_slug, and the rescue at line 244-247 converts it to RateLimited.

Common situations: Cedar ingestion quotas exhausted account- or environment-wide (test env sharing a production Cedar quota); bursts of Study Assist usage generating many Cedar events; Cedar configuration pointing at a throttled endpoint.

Related errors


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/c8068b7702de1fc6. Report an issue: GitHub.

Appendix: source

Thrown at app/services/study_assist.rb:246

        response = CedarClient.prompt(
          prompt:,
          model: llm_config.model_id,
          feature_slug: "study-assist-#{tool_key}",
          root_account_uuid: @course.root_account.uuid,
          current_user: @user,
          document:
        )
      end

      InstStatsd::Statsd.timing(
        "study_assist.cedar_call_duration",
        time.real,
        tags: { tool: tool_key.to_s }
      )

      response.response
    rescue InstructureMiscPlugin::Extensions::CedarClient::CedarLimitReachedError => e
      Rails.logger.warn("Cedar rate limit exceeded for #{tool_key}: #{e.message}")
      raise RateLimited, e.message
    rescue InstructureMiscPlugin::Extensions::CedarClient::CedarClientError => e
      Rails.logger.error(
        "Cedar error for study_assist tool=#{tool_key} " \
        "feature_slug=study-assist-#{tool_key} " \
        "user_global_id=#{@user.global_id}: #{e.message}"
      )
      raise CedarUnavailable, e.message
    end

    # --- Per-tool prompt + response ---

    def prompt_for_cedar(tool_key, llm_config, content)
      substitutions = (tool_key == :summarize) ? { KIND: summarize_kind(content) } : {}
      prompt, = llm_config.generate_prompt_and_options(substitutions:)
      prompt
    end

View on GitHub (pinned to 1c9f0bb801)