instructure/canvas-lms · error · UnconfiguredError

an object with an interface for loading settings must be…

Error message

an object with an interface for loading settings must be specified as 'settings_store'

What it means

CanvasCache::Redis.settings_store lazily returns the injected settings object (something responding to Setting's interface, e.g. canvas's Setting class); at gem load it defaults to MemorySettings. If the module was re-initialized or reset and no store was injected, it raises UnconfiguredError. The gem deliberately avoids depending on canvas directly, so the app must supply its Setting-like store.

Solutions

  1. In app initialization, set CanvasCache::Redis.settings_store = Setting (or a compatible object)
  2. Keep the gem's own default (MemorySettings) by not resetting the module state; rely on @settings_store initialized at load
  3. If boot-order is the issue, wrap consumers so they only touch settings_store after initializers complete
  4. For gem-only usage, inject MemorySettings (or a stub) explicitly

Example fix

// before
# nothing set in initializer
// after
# config/initializers/canvas_cache.rb
CanvasCache::Redis.settings_store = Setting
Defensive patterns

Strategy: validation

Validate before calling

CanvasCache::Redis.settings_store = Setting unless CanvasCache::Redis.instance_variable_get(:@settings_store)

Type guard

def settings_configured?
  CanvasCache::Redis.instance_variable_get(:@settings_store).present?
end

Try / catch

begin
  store = CanvasCache::Redis.settings_store
rescue CanvasCache::UnconfiguredError => e
  Rails.logger.fatal("canvas_cache unconfigured: #{e.message}")
  CanvasCache::Redis.settings_store = MemorySettings.new
end

Prevention

When it happens

Trigger: Accessing CanvasCache::Redis.settings_store (directly or via code reading Redis settings) before the host app has called CanvasCache::Redis.settings_store = Setting in an environment where the default MemorySettings initializer didn't run or was reset.

Common situations: Using canvas_cache outside a full Canvas app (gem tests, another service) without configuring the store; upgrading canvas_cache and the injection line being dropped; code referencing the store during boot before initializers run.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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

Appendix: source

Thrown at gems/canvas_cache/lib/canvas_cache.rb:50

  class << self
    # TODO: Maybe at one point Setting will be
    # a gem on it's own or some other dependable module.
    # For the moment, this is a convenient way to inject
    # this base class without needing to depend on it directly.
    # This is safe to change after initialization, since none of the
    # returned settings are persistently cached in memory
    attr_writer :settings_store

    # Expected interface for this object is:
    #   object.get(setting_name, 'default_value') # [ returning a string ]
    #
    # In this instance, it's expected that canvas is going to inject
    # the Setting class, but we want to break depednencies that directly
    # point to canvas.
    def settings_store
      return @settings_store if @settings_store

      raise UnconfiguredError, "an object with an interface for loading settings must be specified as 'settings_store'"
    end
  end

  @settings_store = MemorySettings.new
end

View on GitHub (pinned to 1c9f0bb801)