scenic-views/scenic · error · Scenic::Adapters::Postgres::MaterializedViewsNotSupportedError
Materialized views require Postgres 9.3 or newer
Error message
Materialized views require Postgres 9.3 or newer
What it means
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.
Source
Thrown at lib/scenic/adapters/postgres.rb:284
end
end
# A decorated ActiveRecord connection object with some Scenic-specific
# methods. Not intended for direct use outside of the Postgres adapter.
#
# @api private
def connection
Connection.new(connectable.connection)
end
private
attr_reader :connectable
delegate :execute, :quote_table_name, to: :connection
def raise_unless_materialized_views_supported
unless connection.supports_materialized_views?
raise MaterializedViewsNotSupportedError
end
end
def raise_unless_concurrent_refresh_supported
unless connection.supports_concurrent_refreshes?
raise ConcurrentRefreshesNotSupportedError
end
end
def refresh_dependencies_for(name, concurrently: false)
Scenic::Adapters::Postgres::RefreshDependencies.call(
name,
self,
connection,
concurrently: concurrently
)
end
endView on GitHub (pinned to f2162dbddb)
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
Example fix
# before: environment pinned to a pre-9.3 server (e.g. postgres:9.2 image) create_view :searches, version: 1, materialized: true # => Materialized views require Postgres 9.3 or newer # after: config/database.yml points at a current server (e.g. postgres:16) # development: # url: postgres://localhost/myapp_dev create_view :searches, version: 1, materialized: true
Defensive patterns
Strategy: validation
Validate before calling
unless ActiveRecord::Base.connection.supports_materialized_views? raise 'connected server predates Postgres 9.3; materialized view migrations will fail' end create_view :searches, version: 1, materialized: true
Type guard
def materialized_views_supported? conn = ActiveRecord::Base.connection return conn.supports_materialized_views? if conn.respond_to?(:supports_materialized_views?) conn.postgresql_version >= 90300 end
Try / catch
begin Scenic.database.refresh_materialized_view(:searches) rescue Scenic::Adapters::Postgres::MaterializedViewsNotSupportedError recompute_without_matview(:searches) # fallback for servers predating 9.3 end
Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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?.
Related errors
- Concurrent materialized view refreshes require Postgres 9.4
- Cannot replace materialized views
- a transaction is required to perform a side-by-side update
- #{method} is reversible only if given a revert_to_version
- version is required
AI-assisted analysis of scenic-views/scenic@f2162dbddb (2026-08-23).
Data as JSON: /api/errors/93a67a6d96101d54.
Report an issue: GitHub.