prestodb/presto · error · TypeError

no abstract type ColumnHandle

Error message

 no abstract type ColumnHandle 

What it means

This TypeError is thrown by the to_json overload for std::shared_ptr<ColumnHandle> in the arrow_flight protocol serializer. The serializer dispatches on the handle's _type/subclass key string; if the key is anything other than the connector's registered tag (here "arrow-flight"), no concrete serialization branch matches and the code reports that the abstract type ColumnHandle has no mapping for that discriminator. It essentially means a ColumnHandle from a different connector (or with a missing/blank type key) was passed into the arrow-flight protocol layer.

Source

Thrown at presto-native-execution/presto_cpp/presto_protocol/connector/arrow_flight/presto_protocol_arrow_flight.cpp:138

void from_json(const json& j, ArrowTableHandle& p) {
  p._type = j["@type"];
  from_json_key(j, "schema", p.schema, "ArrowTableHandle", "String", "schema");
  from_json_key(j, "table", p.table, "ArrowTableHandle", "String", "table");
}
} // namespace facebook::presto::protocol::arrow_flight
namespace facebook::presto::protocol::arrow_flight {
void to_json(json& j, const std::shared_ptr<ColumnHandle>& p) {
  if (p == nullptr) {
    return;
  }
  String type = p->_type;

  if (type == "arrow-flight") {
    j = *std::static_pointer_cast<ArrowColumnHandle>(p);
    return;
  }

  throw TypeError(type + " no abstract type ColumnHandle ");
}

void from_json(const json& j, std::shared_ptr<ColumnHandle>& p) {
  String type;
  try {
    type = p->getSubclassKey(j);
  } catch (json::parse_error& e) {
    throw ParseError(std::string(e.what()) + " ColumnHandle  ColumnHandle");
  }

  if (type == "arrow-flight") {
    std::shared_ptr<ArrowColumnHandle> k =
        std::make_shared<ArrowColumnHandle>();
    j.get_to(*k);
    p = std::static_pointer_cast<ColumnHandle>(k);
    return;
  }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Ensure the ColumnHandle passed to serialization is an ArrowColumnHandle whose _type is set to "arrow-flight"
  2. Check where the handle is constructed/deserialized and fix the subclass key value so it matches the registered tag
  3. Add the missing to_json branch for the actual type tag in presto_protocol_arrow_flight.cpp if a new subclass is legitimate

Example fix

// before
ColumnHandle p = someHiveHandle; // _type == "hive"
to_json(j, std::make_shared<HiveColumnHandle>(p)); // arrow_flight to_json -> TypeError
// after
if (auto* arrow = dynamic_cast<ArrowColumnHandle*>(handle.get())) {
  to_json(j, std::shared_ptr<ArrowColumnHandle>(handle, arrow));
}
Defensive patterns

Strategy: type-guard

Validate before calling

// before serializing with the arrow_flight protocol layer
std::string tag = handle->getType(); // or inspect subclass key
if (tag != "arrow-flight") {
  throw TypeError("cannot serialize " + tag + " ColumnHandle via arrow_flight protocol");
}

Type guard

bool isArrowFlightColumnHandle(const std::shared_ptr<ColumnHandle>& p) {
  return std::dynamic_pointer_cast<ArrowColumnHandle>(p) != nullptr;
}

Try / catch

try {
  to_json(j, columnHandle);
} catch (const TypeError& e) {
  LOG(ERROR) << "ColumnHandle serialization failed: " << e.what();
  throw; // or fall back to the correct connector serializer
}

Prevention

When it happens

Trigger: Calling to_json on a shared_ptr<ColumnHandle> whose getSubclassKey() returns a string other than "arrow-flight" — e.g. a HiveColumnHandle or IcebergColumnHandle routed into arrow-flight JSON conversion, or a deserialized handle whose _type field is empty or corrupt.

Common situations: Mixing connector handles across connectors (Hive/Iceberg/TPC-DS handles reused for arrow-flight tables); hand-built ColumnHandle subclasses that never set the _type discriminator; upgrading protocol definitions so the Java-side type tag changed while native code still expects the old tag.

Related errors


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