{"record":{"id":"c8068b7702de1fc6","repo":"instructure/canvas-lms","slug":"cedar-rate-limit-exceeded-for-tool-key-e-message","errorCode":null,"errorMessage":"Cedar rate limit exceeded for #{tool_key}: #{e.message}","messagePattern":"Cedar rate limit exceeded for #(.+?): #(.+?)","errorType":"console","errorClass":"RateLimited","httpStatus":null,"severity":"warning","filePath":"app/services/study_assist.rb","lineNumber":246,"sourceCode":"        response = CedarClient.prompt(\n          prompt:,\n          model: llm_config.model_id,\n          feature_slug: \"study-assist-#{tool_key}\",\n          root_account_uuid: @course.root_account.uuid,\n          current_user: @user,\n          document:\n        )\n      end\n\n      InstStatsd::Statsd.timing(\n        \"study_assist.cedar_call_duration\",\n        time.real,\n        tags: { tool: tool_key.to_s }\n      )\n\n      response.response\n    rescue InstructureMiscPlugin::Extensions::CedarClient::CedarLimitReachedError => e\n      Rails.logger.warn(\"Cedar rate limit exceeded for #{tool_key}: #{e.message}\")\n      raise RateLimited, e.message\n    rescue InstructureMiscPlugin::Extensions::CedarClient::CedarClientError => e\n      Rails.logger.error(\n        \"Cedar error for study_assist tool=#{tool_key} \" \\\n        \"feature_slug=study-assist-#{tool_key} \" \\\n        \"user_global_id=#{@user.global_id}: #{e.message}\"\n      )\n      raise CedarUnavailable, e.message\n    end\n\n    # --- Per-tool prompt + response ---\n\n    def prompt_for_cedar(tool_key, llm_config, content)\n      substitutions = (tool_key == :summarize) ? { KIND: summarize_kind(content) } : {}\n      prompt, = llm_config.generate_prompt_and_options(substitutions:)\n      prompt\n    end\n","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/services/study_assist.rb#L228-L264","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check Cedar-side quota/limits for the environment and raise them if artificially low","Confirm the feature_slug study-assist-#{tool_key} isn't double-emitting events (e.g., retry loops calling call_cedar repeatedly)","Add backoff/retry with jitter on the caller side for RateLimited originating from Cedar","Verify CedarClient configuration (endpoint, credentials, account) matches the intended environment"],"exampleFix":"// before\ncedar_client.record(event) # CedarLimitReachedError -> RateLimited\n// after\nbegin\n  cedar_client.record(event)\nrescue InstructureMiscPlugin::Extensions::CedarClient::CedarLimitReachedError\n  Rails.logger.info('cedar limit reached, dropping event')\nend","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"begin\n  service.call_cedar(tool_key, llm_config, content)\nrescue StudyAssist::RateLimited => e\n  metrics.increment('study_assist.cedar_limited', tags: { tool: tool_key })\n  # drop or defer the Cedar event\nend","preventionTips":["Alert on Cedar quota usage in the environment","Avoid retry loops that multiply Cedar event emissions","Match Cedar configuration to the correct environment quota"],"tags":["rate-limit","cedar","analytics","upstream"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}