instructure/canvas-lms · error

invalid options - # (must be in # )

Error message

invalid options - #{invalid_keys.inspect} (must be in #{valid_keys.inspect})

What it means

Course.add_setting validates that the opts hash passed when registering a course setting contains only whitelisted keys (:boolean, :default, :inherited, :alias, :arbitrary). Any unknown option key raises this error at registration time, and the invalid/valid key lists are included in the message.

Solutions

  1. Remove or rename the offending keys listed in invalid_keys to ones in valid_keys (boolean, default, inherited, alias, arbitrary).
  2. If you need a free-form string value, pass arbitrary: true and drop any custom type options.
  3. Check the Canvas version's Course.add_setting whitelist; upgrade guides may list renamed options.

Example fix

// before
Course.add_setting(:homeroom_course, {type: :boolean, default: false})

// after
Course.add_setting(:homeroom_course, {boolean: true, default: false})
Defensive patterns

Strategy: validation

Validate before calling

VALID = %i[boolean default inherited alias arbitrary]
bad = opts.except(*VALID).keys
raise ArgumentError, "bad opts #{bad}" if bad.any?

Prevention

When it happens

Trigger: Calling Course.add_setting(:my_setting, typoed_opt: true) or passing a non-supported key like Course.add_setting(:x, {type: :boolean}) during plugin/initializer load.

Common situations: Typo in option names in an initializer or plugin registration; copying options from another add_setting-like API; a Canvas version changed the allowed key set so old registration code now fails.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at app/models/course.rb:4061

  def allow_wiki_comments
    self["allow_wiki_comments"]
  end

  delegate :name, to: :account, prefix: true

  def term_name
    enrollment_term.name
  end

  cattr_accessor :settings_options
  self.settings_options = {}

  def self.add_setting(setting, opts = {})
    setting = setting.to_sym
    settings_options[setting] = opts
    valid_keys = %i[boolean default inherited alias arbitrary]
    invalid_keys = opts.except(*valid_keys).keys
    raise "invalid options - #{invalid_keys.inspect} (must be in #{valid_keys.inspect})" if invalid_keys.any?

    cast_expression = "val.to_s.presence"
    cast_expression = "val" if opts[:arbitrary]
    if opts[:boolean]
      opts[:default] ||= false
      cast_expression = "Canvas::Plugin.value_to_boolean(val)"
    end
    class_eval <<~RUBY, __FILE__, __LINE__ + 1
      def #{setting}
        if Course.settings_options[#{setting.inspect}][:inherited]
          inherited = RequestCache.cache('inherited_course_setting', #{setting.inspect}, self.global_account_id) do
            self.account.send(#{setting.inspect})
          end
          if inherited[:locked] || settings_frd[#{setting.inspect}].nil?
            inherited[:value]
          else
            settings_frd[#{setting.inspect}]
          end

View on GitHub (pinned to 1c9f0bb801)