prestodb/presto · error · IllegalArgumentException

catalog must be present if schema is present

Error message

catalog must be present if schema is present

What it means

ViewExpression's constructor validates that a catalog is present whenever a schema is present, throwing IllegalArgumentException 'catalog must be present if schema is present'. A view/row-filter expression is always anchored to a catalog; a schema without a catalog is an inconsistent, unqualified definition, so the SPI rejects it eagerly.

Source

Thrown at presto-spi/src/main/java/com/facebook/presto/spi/security/ViewExpression.java:35

import static java.util.Objects.requireNonNull;

public class ViewExpression
{
    private final String identity;
    private final Optional<String> catalog;
    private final Optional<String> schema;
    private final String expression;

    public ViewExpression(String identity, Optional<String> catalog, Optional<String> schema, String expression)
    {
        this.identity = requireNonNull(identity, "identity is null");
        this.catalog = requireNonNull(catalog, "catalog is null");
        this.schema = requireNonNull(schema, "schema is null");
        this.expression = requireNonNull(expression, "expression is null");

        if (!catalog.isPresent() && schema.isPresent()) {
            throw new IllegalArgumentException("catalog must be present if schema is present");
        }
    }

    public String getIdentity()
    {
        return identity;
    }

    public Optional<String> getCatalog()
    {
        return catalog;
    }

    public Optional<String> getSchema()
    {
        return schema;
    }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Always supply the catalog: new ViewExpression(identity, Optional.of("catalog"), Optional.of("schema"), expression)
  2. If the expression is truly unqualified, pass Optional.empty() for BOTH catalog and schema
  3. Fix the JSON/config producer to emit the catalog property alongside schema
  4. Add client-side validation that (catalog == null) implies (schema == null) before calling the API

Example fix

// before
new ViewExpression(user, Optional.empty(), Optional.of("sales"), expr); // throws
// after
new ViewExpression(user, Optional.of("hive"), Optional.of("sales"), expr);
// or unqualified:
new ViewExpression(user, Optional.empty(), Optional.empty(), expr);
Defensive patterns

Strategy: validation

Validate before calling

// validate before constructing ViewExpression
if (catalog == null && schema != null) {
    throw new IllegalArgumentException("catalog must be present if schema is present");
}
ViewExpression v = new ViewExpression(identity, catalog, schema, expression);

Type guard

boolean isValidViewExpressionScope(Optional<String> catalog, Optional<String> schema) {
    return schema == null || !schema.isPresent() || (catalog != null && catalog.isPresent());
}

Try / catch

try {
    return new ViewExpression(identity, catalog, schema, expression);
} catch (IllegalArgumentException e) {
    LOG.warn("Invalid view expression scope: %s", e.getMessage());
    // fall back to a fully qualified or fully unqualified expression
    return new ViewExpression(identity, catalog, Optional.empty(), expression);
}

Prevention

When it happens

Trigger: Constructing new ViewExpression(identity, Optional.empty() /*catalog*/, Optional.of("schema") /*schema*/, expression), or deserializing JSON where catalog is null/absent but schema is set — e.g. column masks/row filters defined for access control.

Common situations: Hand-written JSON for view expressions in system access control configs omitting catalog; internal tooling building ViewExpression programmatically and passing empty Optional for catalog; migration scripts that drop the catalog field.

Related errors


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