{"record":{"id":"93a67a6d96101d54","repo":"scenic-views/scenic","slug":"materialized-views-require-postgres-9-3-or-newer","errorCode":null,"errorMessage":"Materialized views require Postgres 9.3 or newer","messagePattern":"Materialized views require Postgres 9\\.3 or newer","errorType":"exception","errorClass":"Scenic::Adapters::Postgres::MaterializedViewsNotSupportedError","httpStatus":null,"severity":"error","filePath":"lib/scenic/adapters/postgres.rb","lineNumber":284,"sourceCode":"        end\n      end\n\n      # A decorated ActiveRecord connection object with some Scenic-specific\n      # methods. Not intended for direct use outside of the Postgres adapter.\n      #\n      # @api private\n      def connection\n        Connection.new(connectable.connection)\n      end\n\n      private\n\n      attr_reader :connectable\n      delegate :execute, :quote_table_name, to: :connection\n\n      def raise_unless_materialized_views_supported\n        unless connection.supports_materialized_views?\n          raise MaterializedViewsNotSupportedError\n        end\n      end\n\n      def raise_unless_concurrent_refresh_supported\n        unless connection.supports_concurrent_refreshes?\n          raise ConcurrentRefreshesNotSupportedError\n        end\n      end\n\n      def refresh_dependencies_for(name, concurrently: false)\n        Scenic::Adapters::Postgres::RefreshDependencies.call(\n          name,\n          self,\n          connection,\n          concurrently: concurrently\n        )\n      end\n    end","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/scenic-views/scenic/blob/f2162dbddb0fb0eb5d4b04d640dcec5303a387e8/lib/scenic/adapters/postgres.rb#L266-L302","documentation":"Scenic's Postgres adapter raises Scenic::Adapters::Postgres::MaterializedViewsNotSupportedError from every materialized-view entry point (create_materialized_view, update_materialized_view, drop_materialized_view, refresh_materialized_view, populated?) when the connected server predates Postgres 9.3, the release that introduced CREATE MATERIALIZED VIEW. The guard consults connection.supports_materialized_views?, which delegates to the Rails adapter method on Rails 4.2+ or falls back to comparing postgresql_version >= 90300. It fires before any SQL is issued, so no partial schema changes are left behind.","triggerScenarios":"Against a server reporting a version below 9.3, any of: create_view :searches, version: 1, materialized: true in a migration; update_view or drop_view with materialized truthy; application code calling Scenic.database.refresh_materialized_view(:searches) or Scenic.database.populated?(:searches).","commonSituations":"CI or staging pinned to an ancient Postgres image while local dev runs a current one; a DATABASE_URL or config/database.yml entry silently pointing at a legacy server; production databases never upgraded past 9.2; a custom Scenic adapter whose connection object does not expose supports_materialized_views?.","solutions":["Run SELECT version(); on the exact server the failing environment connects to (check DATABASE_URL / config/database.yml) and confirm it is older than 9.3","Upgrade that environment to Postgres 9.3 or newer (any modern image such as postgres:16) and re-run the migration or refresh job","If the server cannot be upgraded, stop using materialized views there: drop the materialized option so Scenic creates a plain view, and remove refresh_materialized_view calls"],"exampleFix":"# before: environment pinned to a pre-9.3 server (e.g. postgres:9.2 image)\ncreate_view :searches, version: 1, materialized: true\n# => Materialized views require Postgres 9.3 or newer\n\n# after: config/database.yml points at a current server (e.g. postgres:16)\n# development:\n#   url: postgres://localhost/myapp_dev\ncreate_view :searches, version: 1, materialized: true","handlingStrategy":"validation","validationCode":"unless ActiveRecord::Base.connection.supports_materialized_views?\n  raise 'connected server predates Postgres 9.3; materialized view migrations will fail'\nend\ncreate_view :searches, version: 1, materialized: true","typeGuard":"def materialized_views_supported?\n  conn = ActiveRecord::Base.connection\n  return conn.supports_materialized_views? if conn.respond_to?(:supports_materialized_views?)\n  conn.postgresql_version >= 90300\nend","tryCatchPattern":"begin\n  Scenic.database.refresh_materialized_view(:searches)\nrescue Scenic::Adapters::Postgres::MaterializedViewsNotSupportedError\n  recompute_without_matview(:searches) # fallback for servers predating 9.3\nend","preventionTips":["Pin CI and staging to the same Postgres major version as production; 9.3 is the materialized-view floor","Add a boot-time check that aborts when ActiveRecord::Base.connection.postgresql_version is below 90300 in environments that use materialized views","Keep dev, staging, and prod DATABASE_URL targets consistent so capability drift surfaces before deploy"],"tags":["postgres","database-version","materialized-view","scenic","rails"],"backgroundTag":"database-version-unsupported","analyzedSha":"f2162dbddb0fb0eb5d4b04d640dcec5303a387e8","analyzedAt":"2026-08-23T09:20:35.041Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}