{"record":{"id":"a89e09c92c31f8ea","repo":"instructure/canvas-lms","slug":"unable-to-read-setting-e","errorCode":null,"errorMessage":"Unable to read setting: #{e}","messagePattern":"Unable to read setting: #(.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"app/models/setting.rb","lineNumber":48,"sourceCode":"                     elsif expires_in\n                       # ignore the in-proc cache, but check redis; it will have been properly\n                       # cleared by whoever set it, they just have no way to clear the in-proc cache\n                       @all_settings = MultiCache.fetch(\"all_settings\", &fetch)\n                     else\n                       # use both caches\n                       @all_settings ||= MultiCache.fetch(\"all_settings\", &fetch)\n                     end\n\n      if all_settings.key?(name)\n        all_settings[name]&.to_s\n      else\n        Setting.set(name, default) if set_if_nx\n        default&.to_s\n      end\n    end\n  rescue ActiveRecord::StatementInvalid, ActiveRecord::ConnectionNotEstablished => e\n    # the db may not exist yet\n    Rails.logger&.warn(\"Unable to read setting: #{e}\")\n    default&.to_s\n  end\n\n  # Note that after calling this, you should send SIGHUP to all running Canvas processes\n  def self.set(name, value, secret: nil)\n    s = Setting.where(name:).first_or_initialize\n    s.value = value&.to_s\n    s.secret = secret unless secret.nil?\n    s.save!\n    cache.delete(name)\n    @all_settings = nil\n    MultiCache.delete(\"all_settings\")\n\n    if defined?(Rails::Console)\n      message = Setting.get(\"setting_set_sighup_required_message\", \"** NOTE: After calling `Setting.set`, SIGHUP must be sent to all Canvas processes **\")\n      Rails.logger.info(message)\n    end\n  end","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/models/setting.rb#L30-L66","documentation":"Setting.get reads values from the settings table, but during early boot (rake tasks, initializers, db:create) the database or settings table may not exist yet. Canvas rescues ActiveRecord::StatementInvalid / ConnectionNotEstablished, logs 'Unable to read setting: ...', and falls back to the provided default. It is a graceful-degradation warning, not a fatal failure.","triggerScenarios":"Calling Setting.get (often indirectly from initializers, feature flags, or config loading) before migrations have run, when the settings table doesn't exist, or when no database connection is established (e.g. during assets:precompile or db setup tasks).","commonSituations":"Fresh Canvas checkout without db:migrate; running yarn/webpack builds that boot Rails without a configured DATABASE_URL; CI steps that load the environment before creating the database;短暂 DB outage during boot.","solutions":["Run `bundle exec rake db:migrate` so the settings table exists before code that reads Settings","Ensure DATABASE_URL/database.yml is correct and the database server is reachable","Defer Setting.get calls out of boot/initializers until after DB initialization, or pass an explicit default","If it only appears during asset precompile or db:create, it is expected noise — the default is used"],"exampleFix":"# before (initializer runs before DB exists)\nTIMEOUT = Setting.get('request_timeout', 30).to_i\n\n# after: defer reading until first use\ndef self.request_timeout\n  @request_timeout ||= Setting.get('request_timeout', 30).to_i\nend","handlingStrategy":"fallback","validationCode":"begin\n  ActiveRecord::Base.connection.execute('SELECT 1 FROM settings LIMIT 1')\nrescue ActiveRecord::StatementInvalid, ActiveRecord::ConnectionNotEstablished\n  # DB not ready; use default\nend","typeGuard":"def settings_available?\n  ActiveRecord::Base.connected? &&\n    ActiveRecord::Base.connection.table_exists?(:settings)\nrescue ActiveRecord::ConnectionNotEstablished\n  false\nend","tryCatchPattern":"begin\n  value = Setting.get('my_setting', nil)\nrescue ActiveRecord::StatementInvalid, ActiveRecord::ConnectionNotEstablished\n  value = DEFAULT_MY_SETTING\nend","preventionTips":["Always pass an explicit default to Setting.get","Run db:migrate before booting processes that read Settings","Avoid Setting.get in initializers; read lazily at first use","Ensure DATABASE_URL/database.yml is valid in build/CI environments"],"tags":["ruby","rails","database","boot","settings"],"backgroundTag":"database-query-failed","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"}