prestodb/presto · error · PrestoException

GENERIC_INTERNAL_ERROR

GENERIC_INTERNAL_ERROR

Error message

Unknown plan phase 

What it means

ConnectorPlanOptimizerManager.getOptimizers maps a PlanPhase (LOGICAL or PHYSICAL) to the registered connector optimizer providers. An unknown phase value cannot occur through the enum's normal use, so the default branch throws GENERIC_INTERNAL_ERROR — hitting it means the enum gained a value not handled in the switch, an internal consistency failure.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/planner/ConnectorPlanOptimizerManager.java:61

        checkArgument(planOptimizerProviders.putIfAbsent(connectorId, planOptimizerProvider) == null,
                "ConnectorPlanOptimizerProvider for connector '%s' is already registered", connectorId);
    }

    public void removePlanOptimizerProvider(ConnectorId connectorId)
    {
        requireNonNull(connectorId, "connectorId is null");
        planOptimizerProviders.remove(connectorId);
    }

    public Map<ConnectorId, Set<ConnectorPlanOptimizer>> getOptimizers(PlanPhase phase)
    {
        switch (phase) {
            case LOGICAL:
                return ImmutableMap.copyOf(transformValues(planOptimizerProviders, ConnectorPlanOptimizerProvider::getLogicalPlanOptimizers));
            case PHYSICAL:
                return ImmutableMap.copyOf(transformValues(planOptimizerProviders, ConnectorPlanOptimizerProvider::getPhysicalPlanOptimizers));
            default:
                throw new PrestoException(GENERIC_INTERNAL_ERROR, "Unknown plan phase " + phase);
        }
    }

    public enum PlanPhase
    {
        LOGICAL, PHYSICAL
    }
}

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Update the switch in getOptimizers to handle the new PlanPhase constant
  2. Ensure all cluster nodes run the same build to avoid enum value skew
  3. If not modifying Presto, upgrade to a consistent release and report the trigger to maintainers

Example fix

// before
switch (phase) {
    case LOGICAL: ...; case PHYSICAL: ...;
    default: throw new PrestoException(GENERIC_INTERNAL_ERROR, "Unknown plan phase " + phase);
}
// after
switch (phase) {
    case LOGICAL: ...; case PHYSICAL: ...;
    case RUNTIME: return ImmutableMap.copyOf(transformValues(planOptimizerProviders, ConnectorPlanOptimizerProvider::getRuntimePlanOptimizers));
    default: throw new PrestoException(GENERIC_INTERNAL_ERROR, "Unknown plan phase " + phase);
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Exhaustive handling on your side
boolean supported = phase == PlanPhase.LOGICAL || phase == PlanPhase.PHYSICAL;
if (!supported) throw new IllegalArgumentException("Unsupported phase: " + phase);

Type guard

boolean isKnownPhase(PlanPhase p) {
    return p == PlanPhase.LOGICAL || p == PlanPhase.PHYSICAL;
}

Try / catch

try { manager.getOptimizers(phase); } catch (PrestoException e) { if (e.getErrorCode().equals(GENERIC_INTERNAL_ERROR.toErrorCode()) && e.getMessage().startsWith("Unknown plan phase")) { useDefaultOptimizers(); } else throw e; }

Prevention

When it happens

Trigger: Adding a new PlanPhase enum constant without updating getOptimizers' switch; reflective/deserialization code producing a phase outside LOGICAL/PHYSICAL; called from PlanOptimizers during plan optimization setup.

Common situations: Custom forks of Presto extending PlanPhase; partial upgrades where compiled classes disagree on enum values (mixed coordinator/worker builds).

Related errors


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