{"record":{"id":"a6a42371f0220e8c","repo":"prestodb/presto","slug":"no-abstract-type-plannode","errorCode":null,"errorMessage":" no abstract type PlanNode ","messagePattern":" no abstract type PlanNode ","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"presto-native-execution/presto_cpp/presto_protocol/core/presto_protocol_core.cpp","lineNumber":800,"sourceCode":"  }\n  if (type == \".MergeJoinNode\") {\n    j = *std::static_pointer_cast<MergeJoinNode>(p);\n    return;\n  }\n  if (type == \".WindowNode\") {\n    j = *std::static_pointer_cast<WindowNode>(p);\n    return;\n  }\n  if (type == \".CallDistributedProcedureNode\") {\n    j = *std::static_pointer_cast<CallDistributedProcedureNode>(p);\n    return;\n  }\n  if (type == \"com.facebook.presto.sql.planner.plan.RPCNode\") {\n    j = *std::static_pointer_cast<RPCNode>(p);\n    return;\n  }\n\n  throw TypeError(type + \" no abstract type PlanNode \");\n}\n\nvoid from_json(const json& j, std::shared_ptr<PlanNode>& p) {\n  String type;\n  try {\n    type = p->getSubclassKey(j);\n  } catch (json::parse_error& e) {\n    throw ParseError(std::string(e.what()) + \" PlanNode  PlanNode\");\n  }\n\n  if (type == \".AggregationNode\") {\n    std::shared_ptr<AggregationNode> k = std::make_shared<AggregationNode>();\n    j.get_to(*k);\n    p = std::static_pointer_cast<PlanNode>(k);\n    return;\n  }\n  if (type == \"com.facebook.presto.sql.planner.plan.GroupIdNode\") {\n    std::shared_ptr<GroupIdNode> k = std::make_shared<GroupIdNode>();","sourceCodeStart":782,"sourceCodeEnd":818,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-native-execution/presto_cpp/presto_protocol/core/presto_protocol_core.cpp#L782-L818","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: to_json has branches only up to RPCNode; a new node RemoteSourceNode with _type=\"RemoteSourceNode\" fails\n// after: add to the to_json(PlanNode) dispatch chain:\n// if (type == \"RemoteSourceNode\") {\n//   j = *std::static_pointer_cast<RemoteSourceNode>(p);\n//   return;\n// }","handlingStrategy":"try-catch","validationCode":"// Pre-check node subclass key before serialization\nbool isRegisteredPlanNodeType(const facebook::presto::protocol::PlanNode& node) {\n  static const std::set<std::string> kTypes = {\".AggregationNode\" /*, ...all registered keys...*/, \"com.facebook.presto.sql.planner.plan.RPCNode\"};\n  return kTypes.count(node.getSubclassKey()) > 0;\n}","typeGuard":"bool isSerializable(const std::shared_ptr<facebook::presto::protocol::PlanNode>& p) {\n  return p != nullptr && !p->getSubclassKey().empty();\n}","tryCatchPattern":"try {\n  to_json(j, planNode);\n} catch (const facebook::presto::protocol::TypeError& e) {\n  LOG(ERROR) << \"Unserializable PlanNode subtype: \" << e.what();\n  // abort task submission or fall back to a supported plan\n}","preventionTips":["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."],"tags":["json-serialization","polymorphic-type","presto-native","plan-node"],"backgroundTag":"unknown-polymorphic-subtype","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}