prestodb/presto · critical · PrestoException

GENERIC_INTERNAL_ERROR

GENERIC_INTERNAL_ERROR

Error message

ConnectorMetadata getCommonPartitioningHandle() is implemented without getAlternativeLayout()

What it means

getAlternativeLayoutHandle() defaults to throwing GENERIC_INTERNAL_ERROR with this message. The contract is that if a connector implements getCommonPartitioningHandle() (promising it can transparently convert layout handles to a common partitioning), it must also implement getAlternativeLayoutHandle(). Hitting the default means the connector broke that contract, so the engine reports it as an internal error.

Source

Thrown at presto-spi/src/main/java/com/facebook/presto/spi/connector/ConnectorMetadata.java:185

        }
        else if (layouts.size() > 1) {
            throw new PrestoException(NOT_SUPPORTED, "Connector returned multiple layouts for table " + table);
        }
        return layouts.get(0);
    }

    ConnectorTableLayout getTableLayout(ConnectorSession session, ConnectorTableLayoutHandle handle);

    /**
     * Return a table layout handle whose partitioning is converted to the provided partitioning handle,
     * but otherwise identical to the provided table layout handle.
     * The provided table layout handle must be one that the connector can transparently convert to from
     * the original partitioning handle associated with the provided table layout handle,
     * as promised by {@link #getCommonPartitioningHandle}.
     */
    default ConnectorTableLayoutHandle getAlternativeLayoutHandle(ConnectorSession session, ConnectorTableLayoutHandle tableLayoutHandle, ConnectorPartitioningHandle partitioningHandle)
    {
        throw new PrestoException(GENERIC_INTERNAL_ERROR, "ConnectorMetadata getCommonPartitioningHandle() is implemented without getAlternativeLayout()");
    }

    /**
     * Experimental: if true, the engine will invoke getLayout otherwise, getLayout will not be called.
     */
    @Deprecated
    @Experimental
    default boolean isLegacyGetLayoutSupported(ConnectorSession session, ConnectorTableHandle tableHandle)
    {
        return true;
    }

    /**
     * Return a partitioning handle which the connector can transparently convert both {@code left} and {@code right} into.
     */
    @Deprecated
    default Optional<ConnectorPartitioningHandle> getCommonPartitioningHandle(ConnectorSession session, ConnectorPartitioningHandle left, ConnectorPartitioningHandle right)
    {

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Implement getAlternativeLayoutHandle(ConnectorSession, ConnectorTableLayoutHandle, ConnectorPartitioningHandle) in the connector to translate the layout handle to the common partitioning
  2. If the connector cannot actually convert handles, remove/fix the getCommonPartitioningHandle implementation so it no longer promises common partitioning
  3. Report as a connector bug if using a third-party connector

Example fix

// before: only getCommonPartitioningHandle overridden
// after
@Override
public ConnectorTableLayoutHandle getAlternativeLayoutHandle(ConnectorSession session, ConnectorTableLayoutHandle handle, ConnectorPartitioningHandle partitioningHandle) {
    return ((MyLayoutHandle) handle).withPartitioning((MyPartitioningHandle) partitioningHandle);
}
Defensive patterns

Strategy: validation

Validate before calling

// connector self-check: the pair must be implemented together
@Override
public ConnectorPartitioningHandle getCommonPartitioningHandle(ConnectorSession session, ConnectorPartitioningHandle left, ConnectorPartitioningHandle right) {
    if (getClass().getMethod("getAlternativeLayoutHandle", ConnectorSession.class, ConnectorTableLayoutHandle.class, ConnectorPartitioningHandle.class)
            .getDeclaringClass() == ConnectorMetadata.class) {
        throw new IllegalStateException("getCommonPartitioningHandle requires getAlternativeLayoutHandle");
    }
    return super.getCommonPartitioningHandle(session, left, right);
}

Try / catch

try {
    return metadata.getAlternativeLayoutHandle(session, layoutHandle, partitioningHandle);
} catch (PrestoException e) {
    if (e.getErrorCode() == StandardErrorCode.GENERIC_INTERNAL_ERROR.toErrorCodeCode()) {
        throw new IllegalStateException("Connector contract violation: getCommonPartitioningHandle without getAlternativeLayoutHandle", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: The engine's newTableLayoutHandle path calls getAlternativeLayoutHandle on a connector that implements getCommonPartitioningHandle but not getAlternativeLayoutHandle; the default throws GENERIC_INTERNAL_ERROR.

Common situations: Custom connector development where getCommonPartitioningHandle was implemented (e.g. for CTE/writer repartitioning) but the companion getAlternativeLayoutHandle was forgotten; upgrading a connector partially.

Related errors


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