{"record":{"id":"21861c995b869b7c","repo":"prestodb/presto","slug":"plannode-plannode","errorCode":null,"errorMessage":" PlanNode  PlanNode","messagePattern":" PlanNode  PlanNode","errorType":"exception","errorClass":"ParseError","httpStatus":null,"severity":"error","filePath":"presto-native-execution/presto_cpp/presto_protocol/core/presto_protocol_core.cpp","lineNumber":808,"sourceCode":"  }\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>();\n    j.get_to(*k);\n    p = std::static_pointer_cast<PlanNode>(k);\n    return;\n  }\n  if (type == \".DeleteNode\") {\n    std::shared_ptr<DeleteNode> k = std::make_shared<DeleteNode>();\n    j.get_to(*k);\n    p = std::static_pointer_cast<PlanNode>(k);","sourceCodeStart":790,"sourceCodeEnd":826,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-native-execution/presto_cpp/presto_protocol/core/presto_protocol_core.cpp#L790-L826","documentation":"from_json for std::shared_ptr<PlanNode> first extracts the subclass discriminator with p->getSubclassKey(j). If that step throws a json::parse_error (malformed JSON, or the document is not an object containing the expected '@type' key), the library wraps it and rethrows ParseError(std::string(e.what()) + \" PlanNode  PlanNode\"). The doubled type name is just the generated message format; the real diagnostic is the nlohmann parse_error text prepended to it.","triggerScenarios":"Calling from_json(json, std::shared_ptr<PlanNode>&) with input that fails JSON parsing or lacks a readable '@type' discriminator — e.g. a truncated plan fragment body, a non-object JSON value (array/string/number), or an HTTP exchange payload that returned an error page instead of plan JSON.","commonSituations":"Coordinator returned an HTTP error body (HTML/text) where the native worker expected plan JSON; truncated or corrupted exchange payloads; sending the wrong endpoint's response into the plan deserializer; encoding/charset issues corrupting the JSON.","solutions":["Read the prepended json::parse_error text (e.what()) to find the exact byte offset and cause of the malformed JSON.","Log the raw response body received before deserialization to confirm a valid plan JSON object with an '@type' field was received.","Check the coordinator endpoint/HTTP status handling: reject non-200 or non-JSON responses before calling from_json.","Upgrade/align coordinator and native versions if the payload format changed (e.g. discriminator key renamed)."],"exampleFix":"// before: blindly parse whatever came back\n// auto plan = resp.body; from_json(json::parse(plan), planNode); // ParseError on HTML error page\n// after: guard the response first\n// if (resp.status != 200 || resp.body.empty() || resp.body.front() != '{') throw std::runtime_error(\"bad plan payload\");\n// from_json(json::parse(resp.body), planNode);","handlingStrategy":"validation","validationCode":"// Validate plan payload before from_json\nbool isValidPlanNodePayload(const nlohmann::json& j) {\n  return j.is_object() && j.contains(\"@type\") && j[\"@type\"].is_string();\n}\n// usage:\n// nlohmann::json j = nlohmann::json::parse(body, nullptr, /*allow_exceptions=*/false);\n// if (j.is_discarded() || !isValidPlanNodePayload(j)) throw std::invalid_argument(\"bad plan json\");","typeGuard":null,"tryCatchPattern":"try {\n  from_json(j, planNode);\n} catch (const facebook::presto::protocol::ParseError& e) {\n  LOG(ERROR) << \"PlanNode payload unparseable: \" << e.what();\n  // inspect raw body, re-request the fragment\n}","preventionTips":["Check HTTP status/content-type before deserializing exchange bodies.","Never feed error pages or truncated bodies into from_json.","Use non-throwing json::parse (is_discarded) as a cheap pre-filter.","Log the raw payload whenever ParseError is raised."],"tags":["json-parse-error","malformed-json","presto-native","plan-node"],"backgroundTag":"malformed-json-payload","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"}