instructure/canvas-lms · warning · RruleValidationError
Missing INTERVAL
Error message
Missing INTERVAL
What it means
rrule_validate_common_opts requires an INTERVAL key in the parsed RRULE options before computing a natural-language description; without it, RruleValidationError 'Missing INTERVAL' is raised (then logged and swallowed to nil by rrule_to_natural_language's rescue).
Solutions
- Default INTERVAL to 1 when absent before calling the helper: rropts['INTERVAL'] ||= 1.
- Fix the data: rewrite stored rrule strings to include INTERVAL.
- Normalize at import time so all stored RRULEs carry explicit INTERVAL.
- Rescue RruleValidationError in the JSON rendering and omit the natural-language field gracefully.
Example fix
// before rropts = RruleHelper.rrule_parse(event.rrule) desc = helper.rrule_to_natural_language(event.rrule) // after rropts = RruleHelper.rrule_parse(event.rrule) rropts['INTERVAL'] ||= '1' desc = helper.rrule_to_natural_language(event.rrule)
Defensive patterns
Strategy: validation
Validate before calling
rropts['INTERVAL'] ||= '1'
raise ArgumentError, 'missing INTERVAL' unless rropts.key?('INTERVAL') Try / catch
begin desc = rrule_to_natural_language(rrule) rescue RruleValidationError desc = nil end
Prevention
- RFC 5545 defaults INTERVAL to 1 — inject it when absent
- Normalize all imported RRULEs to carry explicit INTERVAL
- Add a model-level validation for RRULE option completeness
When it happens
Trigger: Rendering calendar_event_json for an event whose rrule string omits INTERVAL, e.g. 'RRULE:FREQ=DAILY;COUNT=5' (RFC 5545 makes INTERVAL default 1, so producers often omit it).
Common situations: ICS imports from producers that legally omit INTERVAL; hand-authored rrule strings in seeds/tests; legacy rows written before validation existed.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/5982cbe19e545bb4.
Report an issue: GitHub.
Appendix: source
Thrown at app/helpers/rrule_helper.rb:56
parse_weekly(rropts)
when "MONTHLY"
parse_monthly(rropts)
when "YEARLY"
parse_yearly(rropts)
else
raise RruleValidationError, I18n.t("Invalid FREQ '%{freq}'", freq: rropts["FREQ"])
end
rescue => e
logger.error "RRULE to natural language failure: #{e}"
nil
end
def rrule_parse(rrule)
Hash[*rrule.sub(/^RRULE:/, "").split(/[;=]/)]
end
def rrule_validate_common_opts(rropts)
raise RruleValidationError, I18n.t("Missing INTERVAL") unless rropts.key?("INTERVAL")
raise RruleValidationError, I18n.t("INTERVAL must be > 0") unless rropts["INTERVAL"].to_i > 0
# We do not support never ending series because each event in the series
# must get created in the db to support the paginated calendar_events api
raise RruleValidationError, I18n.t("Missing COUNT or UNTIL") unless rropts.key?("COUNT") || rropts.key?("UNTIL")
if rropts.key?("COUNT")
raise RruleValidationError, I18n.t("COUNT must be > 0") unless rropts["COUNT"].to_i > 0
raise RruleValidationError, I18n.t("COUNT must be <= %{limit}", limit: RruleHelper::RECURRING_EVENT_LIMIT) unless rropts["COUNT"].to_i <= RruleHelper::RECURRING_EVENT_LIMIT
else
begin
format_date(rropts["UNTIL"])
rescue
raise RruleValidationError, I18n.t("Invalid UNTIL '%{until_date}'", until_date: rropts["UNTIL"])
end
end
end
View on GitHub (pinned to 1c9f0bb801)