prestodb/presto · error · PinotException

PINOT_INVALID_SEGMENT_QUERY_GENERATED

PINOT_INVALID_SEGMENT_QUERY_GENERATED

Error message

Query and segmentsToQuery must be set

What it means

PinotProxyGrpcRequestBuilder.build() validates that the request payload type has been set and that at least one segment was supplied before constructing the Server.ServerRequest. If payloadType is null or the segments list is empty, the builder state is incomplete and it throws PinotException with code PINOT_INVALID_SEGMENT_QUERY_GENERATED ('Query and segmentsToQuery must be set').

Source

Thrown at presto-pinot-toolkit/src/main/java/com/facebook/presto/pinot/query/PinotProxyGrpcRequestBuilder.java:102

        return this;
    }

    public PinotProxyGrpcRequestBuilder addExtraMetadata(Map<String, String> extraMetadata)
    {
        this.extraMetadata.putAll(extraMetadata);
        return this;
    }

    public PinotProxyGrpcRequestBuilder setSegments(List<String> segments)
    {
        this.segments = segments;
        return this;
    }

    public Server.ServerRequest build()
    {
        if (payloadType == null || segments.isEmpty()) {
            throw new PinotException(PinotErrorCode.PINOT_INVALID_SEGMENT_QUERY_GENERATED, Optional.empty(), "Query and segmentsToQuery must be set");
        }
        if (!payloadType.equals(CommonConstants.Query.Request.PayloadType.SQL)) {
            throw new RuntimeException("Only [SQL] Payload type is allowed: " + payloadType);
        }
        Map<String, String> metadata = new HashMap<>();
        metadata.put(CommonConstants.Query.Request.MetadataKeys.REQUEST_ID, Integer.toString(requestId));
        metadata.put(CommonConstants.Query.Request.MetadataKeys.BROKER_ID, brokerId);
        metadata.put(CommonConstants.Query.Request.MetadataKeys.ENABLE_TRACE, Boolean.toString(enableTrace));
        metadata.put(CommonConstants.Query.Request.MetadataKeys.ENABLE_STREAMING, Boolean.toString(enableStreaming));
        metadata.put(CommonConstants.Query.Request.MetadataKeys.PAYLOAD_TYPE, payloadType);
        if (this.hostName != null) {
            metadata.put(KEY_OF_PROXY_GRPC_FORWARD_HOST, this.hostName);
        }
        if (this.port > 0) {
            metadata.put(KEY_OF_PROXY_GRPC_FORWARD_PORT, String.valueOf(this.port));
        }
        extraMetadata.forEach((k, v) -> metadata.put(k, v));
        return Server.ServerRequest.newBuilder()

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Ensure the query was generated successfully and check why segment selection yielded an empty list — verify the table exists in Pinot and has segments (allSegments/online segments).
  2. Call all required builder setters (query/payloadType and segmentsToQuery) before build(); inspect the builder call site for conditional code that skips setters.
  3. If the table is empty or segments are offline, fix Pinot cluster state (reload/upload segments) so the broker returns segments to query.
  4. Guard the build() call: only construct the gRPC request when the generated Pinot query contains at least one segment.

Example fix

// before
Server.ServerRequest req = new PinotProxyGrpcRequestBuilder(...).build();

// after
if (segmentsToQuery.isEmpty()) {
  throw new IllegalStateException("No segments selected for table " + tableName);
}
Server.ServerRequest req = new PinotProxyGrpcRequestBuilder(...)
    .setPayloadType(SQL)
    .setSegments(segmentsToQuery)
    .build();
Defensive patterns

Strategy: validation

Validate before calling

// Validate builder state before build():
if (payloadType == null) throw new IllegalStateException("payloadType not set");
if (segmentsToQuery == null || segmentsToQuery.isEmpty()) {
    throw new IllegalStateException("no segments selected for query " + sql);
}
Server.ServerRequest req = builder.build();

Type guard

boolean canBuild(PinotProxyGrpcRequestBuilder b) {
    return b != null && b.hasPayloadType() && b.segmentCount() > 0; // adapt to builder accessors
}

Try / catch

try {
    Server.ServerRequest req = builder.build();
} catch (PinotException e) {
    if (PinotErrorCode.PINOT_INVALID_SEGMENT_QUERY_GENERATED.toErrorCodeCode().equals(e.getErrorCode().getName())) {
        // regenerate the plan or skip gRPC path; fall back to broker HTTP query
    } else throw e;
}

Prevention

When it happens

Trigger: Using the Pinot gRPC proxy request builder without calling withPayloadType/query (payloadType stays null) or without adding any segments via withSegments/withSegment, then calling build().

Common situations: Programmatic use of the Pinot gRPC path where an upstream query-generation step produced zero segments (e.g. table has no segments, or routing returned nothing), or a builder misuse where setters were skipped; integration tests constructing requests manually.

Related errors


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