prestodb/presto · error · IllegalStateException

Materialized view owner is required when legacy_materialized

Error message

Materialized view owner is required when legacy_materialized_views=false. This indicates a materialized view created before the security mode feature was added. Set session property legacy_materialized_views=true to refresh this view, or drop and recreate the view.

What it means

buildOwnerSession enforces that materialized views created under the newer security model (legacy_materialized_views=false) have an owner recorded. When the owner is absent (view predates the security-mode feature), refresh cannot establish the owner identity, so it fails fast with this IllegalStateException and guidance to use the legacy flag or recreate the view.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/MaterializedViewUtils.java:111

    public static final QualifiedName APPROX_DISTINCT = QualifiedName.of("APPROX_DISTINCT");
    public static final QualifiedName APPROX_SET = QualifiedName.of("APPROX_SET");

    public static final Set<QualifiedName> ASSOCIATIVE_REWRITE_FUNCTIONS = ImmutableSet.of(MIN, MAX, SUM, COUNT);

    // TODO: Add count to NonAssociativeFunctionHandler, add more functions
    public static final Map<QualifiedName, MaterializedViewUtils.NonAssociativeFunctionHandler> NON_ASSOCIATIVE_REWRITE_FUNCTIONS = ImmutableMap.of(
            AVG, new MaterializedViewUtils.AvgRewriteHandler(),
            APPROX_DISTINCT, new MaterializedViewUtils.ApproxDistinctRewriteHandler());

    public static final Set<QualifiedName> SUPPORTED_FUNCTION_CALLS = Sets.union(ASSOCIATIVE_REWRITE_FUNCTIONS, NON_ASSOCIATIVE_REWRITE_FUNCTIONS.keySet());

    private MaterializedViewUtils() {}

    public static Session buildOwnerSession(Session session, Optional<String> owner, SessionPropertyManager sessionPropertyManager, String catalog, String schema)
    {
        // When legacy_materialized_views=false, owner must be present for REFRESH operations
        if (!isLegacyMaterializedViews(session) && !owner.isPresent()) {
            throw new IllegalStateException(
                    "Materialized view owner is required when legacy_materialized_views=false. " +
                    "This indicates a materialized view created before the security mode feature was added. " +
                    "Set session property legacy_materialized_views=true to refresh this view, or drop and recreate the view.");
        }

        Identity identity = getOwnerIdentity(owner, session);

        Session.SessionBuilder builder = Session.builder(sessionPropertyManager)
                .setQueryId(session.getQueryId())
                .setTransactionId(session.getTransactionId().orElse(null))
                .setIdentity(identity)
                .setSource(session.getSource().orElse(null))
                .setCatalog(catalog)
                .setSchema(schema)
                .setTimeZoneKey(session.getTimeZoneKey())
                .setLocale(session.getLocale())
                .setRemoteUserAddress(session.getRemoteUserAddress().orElse(null))
                .setUserAgent(session.getUserAgent().orElse(null))

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Set session property legacy_materialized_views=true for the refresh session of this old view
  2. Drop and recreate the materialized view so an owner is recorded in its metadata
  3. Update the view metadata/owner if the deployment provides a migration path
  4. Audit old views after upgrading and migrate them proactively

Example fix

// before
REFRESH MATERIALIZED VIEW catalog.schema.mv;
// after
SET SESSION catalog.legacy_materialized_views = true;
REFRESH MATERIALIZED VIEW catalog.schema.mv;
Defensive patterns

Strategy: validation

Validate before calling

-- check owner before refresh
SELECT owner FROM system.metadata.materialized_views WHERE ... ;
-- if owner is null, set: SET SESSION <catalog>.legacy_materialized_views = true;

Try / catch

try { refreshMaterializedView(...); } catch (IllegalStateException e) { if (e.getMessage().contains("Materialized view owner is required")) { setSessionLegacyMaterializedViews(true); retry(); } else { throw e; } }

Prevention

When it happens

Trigger: Running REFRESH MATERIALIZED VIEW (or equivalent buildOwnerSession path) with legacy_materialized_views=false while the view metadata has Optional.empty() owner, typically a view created before the owner/security feature was introduced.

Common situations: Upgraded clusters: old materialized views lack owners; ops run scheduled refresh jobs against them; users unset legacy_materialized_views cluster-wide but old views remain.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/b45c49fdac4630d3. Report an issue: GitHub.