instructure/canvas-lms · warning
You've hit the study tools rate limit. Try again later.
Error message
You've hit the study tools rate limit. Try again later.
What it means
StudyAssistController#create rescues StudyAssist::RateLimited raised by the upstream study-tools/Cedar pipeline and renders a 429 with this message. The client exceeded the configured rate limit for AI study tools prompts within the allowed window.
Solutions
- Wait for the rate-limit window to elapse and retry with backoff
- Reduce request frequency / batch prompts in the client
- Check the rate limit configuration (per user/account) and raise it if legitimately too low
- Record which request triggered it via the logged 'Study Assist rate limit' warning and throttle client-side
Example fix
// before
// client retries immediately on failure
for (const p of prompts) await send(p)
// after
for (const p of prompts) {
const res = await send(p)
if (res.status === 429) await sleep(Math.pow(2, attempt++) * 1000)
} Defensive patterns
Strategy: retry
Try / catch
const res = await fetch(url, opts)
if (res.status === 429) {
await sleep(Math.min(backoffMs *= 2, 60_000))
return retry()
} Prevention
- Throttle client request rates within documented limits
- Use exponential backoff with jitter on 429s
- Batch prompts instead of sending one per request
- Monitor per-user usage against the limit
When it happens
Trigger: A user or integration POSTs prompts to the study assist create endpoint more times than the per-user/account limit allows in the rate window, causing the service layer to raise StudyAssist::RateLimited.
Common situations: Loops or batch scripts hammering the study assist endpoint; shared accounts consumed by multiple users; classroom-wide usage spikes; aggressively-retrying clients after failures.
Related errors
- category has reached the maximum number of tags
- Cedar rate limit exceeded for #
- rate limit exceeded
- Rate limit exceeded
- Rate limit must be either nil, or hash with :limit and…
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/86ac5bb9d01b61bc.
Report an issue: GitHub.
Appendix: source
Thrown at app/controllers/study_assist_controller.rb:75
record_metric("unknown", "unsupported")
render json: { error: t("Study tools aren't available for this prompt.") }, status: :unprocessable_content
rescue StudyAssist::ToolDisabled
record_metric(tool_tag(request_body[:prompt]), "unsupported")
render json: { error: t("This study tool isn't currently available.") }, status: :forbidden
rescue StudyAssist::UnsupportedContentType
record_metric(tool_tag(request_body[:prompt]), "unsupported")
render json: { error: t("Study tools aren't available for this file type.") }, status: :unprocessable_content
rescue StudyAssist::ContentUnavailable => e
record_metric(tool_tag(request_body[:prompt]), "content_unavailable")
Rails.logger.info("Study Assist content unavailable: #{e.message}")
render json: { error: t("Content isn't available for study tools.") }, status: :unprocessable_content
rescue StudyAssist::ContentTooLarge
record_metric(tool_tag(request_body[:prompt]), "too_large")
render json: { error: t("Content is too long for study tools.") }, status: :unprocessable_content
rescue StudyAssist::RateLimited => e
record_metric(tool_tag(request_body[:prompt]), "rate_limit")
Rails.logger.warn("Study Assist rate limit: #{e.message}")
render json: { error: t("You've hit the study tools rate limit. Try again later.") }, status: :too_many_requests
rescue StudyAssist::CedarUnavailable => e
record_metric(tool_tag(request_body[:prompt]), "cedar_error")
Rails.logger.error("Study Assist Cedar failure: #{e.message}")
render json: { error: t("Study tools are temporarily unavailable. Please try again.") }, status: :bad_gateway
end
private
def require_study_assist_enabled
return if @context.is_a?(Course) && @context.feature_enabled?(:study_assist)
render json: { error: t("Study tools aren't enabled for this course.") }, status: :not_found
false
end
def require_student_access
authorized_action(@context, @current_user, :participate_as_student)
endView on GitHub (pinned to 1c9f0bb801)