prestodb/presto · error · PrestoException
INVALID_TABLE_PROPERTY
INVALID_TABLE_PROPERTY
Error message
%s must be positive, got %d
What it means
IcebergMaterializedViewProperties validates MV table properties. The max_snapshots_per_refresh property is parsed as an int and must be strictly positive; a value of zero or negative throws PrestoException INVALID_TABLE_PROPERTY with '%s must be positive, got %d'.
Source
Thrown at presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergMaterializedViewProperties.java:135
null,
false),
PRESTO_MATERIALIZED_VIEW_USE_TIMESTAMP_BASED_STALENESS),
updatable(
new PropertyMetadata<>(
MAX_SNAPSHOTS_PER_REFRESH,
"Maximum number of snapshots consumed per base table per refresh. " +
"Unset falls back to the session default.",
INTEGER,
Integer.class,
null,
false,
value -> {
if (value == null) {
return null;
}
int parsed = ((Number) value).intValue();
if (parsed <= 0) {
throw new PrestoException(INVALID_TABLE_PROPERTY,
format("%s must be positive, got %d", MAX_SNAPSHOTS_PER_REFRESH, parsed));
}
return parsed;
},
object -> object),
PRESTO_MATERIALIZED_VIEW_MAX_SNAPSHOTS_PER_REFRESH,
value -> Integer.toString((Integer) value)));
private static final Map<String, MaterializedViewProperty> MV_ONLY_PROPERTIES_BY_NAME =
Maps.uniqueIndex(MV_ONLY_PROPERTIES, property -> property.metadata().getName());
private final List<PropertyMetadata<?>> materializedViewProperties;
@Inject
public IcebergMaterializedViewProperties(IcebergTableProperties tableProperties)
{
requireNonNull(tableProperties, "tableProperties is null");
View on GitHub (pinned to 55bb57d202)
Solutions
- Set the property to a positive integer (e.g. 10) instead of 0 or a negative value
- Remove the property entirely to use the default behavior instead of 0
- Validate any templated/config-driven value before applying it (coerce and check > 0)
- Consult the property definition in IcebergMaterializedViewProperties for the accepted range
Example fix
// before ALTER MATERIALIZED VIEW sales.daily_mv SET PROPERTIES max_snapshots_per_refresh = 0; // after ALTER MATERIALIZED VIEW sales.daily_mv SET PROPERTIES max_snapshots_per_refresh = 10;
Defensive patterns
Strategy: validation
Validate before calling
-- Validate before applying:
-- ensure the value is an integer > 0
SELECT IF(CAST(${max_snapshots_per_refresh} AS BIGINT) > 0, 'ok', 'invalid') AS check;
-- or simply: ALTER ... SET PROPERTIES max_snapshots_per_refresh = 10; Type guard
// application-side guard
boolean isValidMaxSnapshots(Number v) {
return v != null && v.intValue() > 0;
} Try / catch
try {
stmt.execute("ALTER MATERIALIZED VIEW sales.daily_mv SET PROPERTIES max_snapshots_per_refresh = " + value);
} catch (SQLException e) {
if (e.getMessage() != null && e.getMessage().contains("must be positive")) {
// clamp to a positive default or remove the property, then retry
} else { throw e; }
} Prevention
- Validate config/templated values (must be > 0) before emitting DDL
- Treat 0 as 'use default' by omitting the property, not passing 0
- Add unit checks around property-generating code paths
- Document accepted ranges for MV properties in runbooks
When it happens
Trigger: ALTER MATERIALIZED VIEW ... SET PROPERTIES max_snapshots_per_refresh = 0 (or negative), or a CREATE MATERIALIZED VIEW ... WITH (max_snapshots_per_refresh = <=0) statement.
Common situations: Copy-pasting a config where the value is meant to be 'unlimited' (using 0); arithmetic/templating bugs producing 0 or negative values; misunderstanding that 0 means 'no limit'.
Related errors
- INVALID_MATERIALIZED_VIEW_PROPERTY
- Invalid Hive object for %s.%s
- iceberg.target-max-file-size must be at least 1 byte
- ALREADY_EXISTS
- NOT_FOUND
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/6ae2b573d80a2592.
Report an issue: GitHub.