prestodb/presto · error · TypeError
no abstract type PlanNode
Error message
no abstract type PlanNode
What it means
to_json for std::shared_ptr<PlanNode> serializes a polymorphic plan node by reading the node's _type key and dispatching to the matching concrete class (AggregationNode, RPCNode, etc.). If the plan node's subclass key matches none of the registered PlanNode subclasses, the serializer throws TypeError('<type> no abstract type PlanNode'). This indicates a PlanNode subtype present in memory that this build of the protocol library cannot serialize.
Source
Thrown at presto-native-execution/presto_cpp/presto_protocol/core/presto_protocol_core.cpp:800
}
if (type == ".MergeJoinNode") {
j = *std::static_pointer_cast<MergeJoinNode>(p);
return;
}
if (type == ".WindowNode") {
j = *std::static_pointer_cast<WindowNode>(p);
return;
}
if (type == ".CallDistributedProcedureNode") {
j = *std::static_pointer_cast<CallDistributedProcedureNode>(p);
return;
}
if (type == "com.facebook.presto.sql.planner.plan.RPCNode") {
j = *std::static_pointer_cast<RPCNode>(p);
return;
}
throw TypeError(type + " no abstract type PlanNode ");
}
void from_json(const json& j, std::shared_ptr<PlanNode>& p) {
String type;
try {
type = p->getSubclassKey(j);
} catch (json::parse_error& e) {
throw ParseError(std::string(e.what()) + " PlanNode PlanNode");
}
if (type == ".AggregationNode") {
std::shared_ptr<AggregationNode> k = std::make_shared<AggregationNode>();
j.get_to(*k);
p = std::static_pointer_cast<PlanNode>(k);
return;
}
if (type == "com.facebook.presto.sql.planner.plan.GroupIdNode") {
std::shared_ptr<GroupIdNode> k = std::make_shared<GroupIdNode>();View on GitHub (pinned to 55bb57d202)
Solutions
- Align versions: rebuild/upgrade presto-native-execution to the version matching the coordinator so the PlanNode subclass is registered.
- Log/inspect the node's _type value in the error and check whether the corresponding if (type == "...") branch exists in to_json for PlanNode.
- Disable or avoid the feature/connector producing the unsupported plan node until support lands.
- Add the missing branch (construct + serialize the concrete class) in the PlanNode to_json function for the new subtype.
Example fix
// before: to_json has branches only up to RPCNode; a new node RemoteSourceNode with _type="RemoteSourceNode" fails
// after: add to the to_json(PlanNode) dispatch chain:
// if (type == "RemoteSourceNode") {
// j = *std::static_pointer_cast<RemoteSourceNode>(p);
// return;
// } Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check node subclass key before serialization
bool isRegisteredPlanNodeType(const facebook::presto::protocol::PlanNode& node) {
static const std::set<std::string> kTypes = {".AggregationNode" /*, ...all registered keys...*/, "com.facebook.presto.sql.planner.plan.RPCNode"};
return kTypes.count(node.getSubclassKey()) > 0;
} Type guard
bool isSerializable(const std::shared_ptr<facebook::presto::protocol::PlanNode>& p) {
return p != nullptr && !p->getSubclassKey().empty();
} Try / catch
try {
to_json(j, planNode);
} catch (const facebook::presto::protocol::TypeError& e) {
LOG(ERROR) << "Unserializable PlanNode subtype: " << e.what();
// abort task submission or fall back to a supported plan
} Prevention
- Rebuild the native library whenever the coordinator gains new plan node types.
- Cover all plan node subtypes in serialization tests.
- Feature-gate coordinator features that emit non-native plan nodes.
- Assert node _type values in fixtures match registered discriminators exactly.
When it happens
Trigger: Serializing (to_json on a std::shared_ptr<PlanNode>) a node whose getSubclassKey() value is not among the implemented if-branches (e.g. a newly added or connector-specific plan node missing from the registry). Reached from plan serialization paths such as sending plan fragments to native workers.
Common situations: New coordinator emits a plan node type added after the native library was built; custom/enterprise plan nodes (like RPCNode) used with an open-source build; version skew between coordinator and native worker; manually constructed PlanNode subclasses in tests with unexpected _type.
Related errors
- {type} no abstract type ExecutionWriterTarget
- PlanNode PlanNode
- DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION
- no abstract type ColumnHandle
- no abstract type ColumnHandle
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/a6a42371f0220e8c.
Report an issue: GitHub.