{"record":{"id":"b45c49fdac4630d3","repo":"prestodb/presto","slug":"materialized-view-owner-is-required-when-legacy-ma","errorCode":null,"errorMessage":"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.","messagePattern":"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\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/sql/MaterializedViewUtils.java","lineNumber":111,"sourceCode":"    public static final QualifiedName APPROX_DISTINCT = QualifiedName.of(\"APPROX_DISTINCT\");\n    public static final QualifiedName APPROX_SET = QualifiedName.of(\"APPROX_SET\");\n\n    public static final Set<QualifiedName> ASSOCIATIVE_REWRITE_FUNCTIONS = ImmutableSet.of(MIN, MAX, SUM, COUNT);\n\n    // TODO: Add count to NonAssociativeFunctionHandler, add more functions\n    public static final Map<QualifiedName, MaterializedViewUtils.NonAssociativeFunctionHandler> NON_ASSOCIATIVE_REWRITE_FUNCTIONS = ImmutableMap.of(\n            AVG, new MaterializedViewUtils.AvgRewriteHandler(),\n            APPROX_DISTINCT, new MaterializedViewUtils.ApproxDistinctRewriteHandler());\n\n    public static final Set<QualifiedName> SUPPORTED_FUNCTION_CALLS = Sets.union(ASSOCIATIVE_REWRITE_FUNCTIONS, NON_ASSOCIATIVE_REWRITE_FUNCTIONS.keySet());\n\n    private MaterializedViewUtils() {}\n\n    public static Session buildOwnerSession(Session session, Optional<String> owner, SessionPropertyManager sessionPropertyManager, String catalog, String schema)\n    {\n        // When legacy_materialized_views=false, owner must be present for REFRESH operations\n        if (!isLegacyMaterializedViews(session) && !owner.isPresent()) {\n            throw new IllegalStateException(\n                    \"Materialized view owner is required when legacy_materialized_views=false. \" +\n                    \"This indicates a materialized view created before the security mode feature was added. \" +\n                    \"Set session property legacy_materialized_views=true to refresh this view, or drop and recreate the view.\");\n        }\n\n        Identity identity = getOwnerIdentity(owner, session);\n\n        Session.SessionBuilder builder = Session.builder(sessionPropertyManager)\n                .setQueryId(session.getQueryId())\n                .setTransactionId(session.getTransactionId().orElse(null))\n                .setIdentity(identity)\n                .setSource(session.getSource().orElse(null))\n                .setCatalog(catalog)\n                .setSchema(schema)\n                .setTimeZoneKey(session.getTimeZoneKey())\n                .setLocale(session.getLocale())\n                .setRemoteUserAddress(session.getRemoteUserAddress().orElse(null))\n                .setUserAgent(session.getUserAgent().orElse(null))","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/sql/MaterializedViewUtils.java#L93-L129","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set session property legacy_materialized_views=true for the refresh session of this old view","Drop and recreate the materialized view so an owner is recorded in its metadata","Update the view metadata/owner if the deployment provides a migration path","Audit old views after upgrading and migrate them proactively"],"exampleFix":"// before\nREFRESH MATERIALIZED VIEW catalog.schema.mv;\n// after\nSET SESSION catalog.legacy_materialized_views = true;\nREFRESH MATERIALIZED VIEW catalog.schema.mv;","handlingStrategy":"validation","validationCode":"-- check owner before refresh\nSELECT owner FROM system.metadata.materialized_views WHERE ... ;\n-- if owner is null, set: SET SESSION <catalog>.legacy_materialized_views = true;","typeGuard":null,"tryCatchPattern":"try { refreshMaterializedView(...); } catch (IllegalStateException e) { if (e.getMessage().contains(\"Materialized view owner is required\")) { setSessionLegacyMaterializedViews(true); retry(); } else { throw e; } }","preventionTips":["After upgrading, audit and recreate legacy materialized views so owners are recorded","Keep legacy_materialized_views=true only for refresh jobs touching old views","Document the security-mode migration for MV owners","Include owner in MV DDL reviews"],"tags":["materialized-view","security","migration","owner-required"],"backgroundTag":"materialized-view-owner-missing","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}