{"record":{"id":"1000c1ed849fb6d4","repo":"HKUDS/Vibe-Trading","slug":"n-port-document-did-not-parse-exc","errorCode":null,"errorMessage":"N-PORT document did not parse: {exc}","messagePattern":"N-PORT document did not parse: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/etf_holdings_tool.py","lineNumber":755,"sourceCode":"\n\ndef _parse_nport(xml_text: str) -> dict[str, Any]:\n    \"\"\"Parse an N-PORT ``primary_doc.xml`` into fund metadata plus holdings.\n\n    Args:\n        xml_text: The raw filing document.\n\n    Returns:\n        ``{series_id, series_name, registrant, as_of, fiscal_year_end,\n        total_assets_usd, net_assets_usd, holdings}``.\n\n    Raises:\n        RuntimeError: When the document is not parseable XML.\n    \"\"\"\n    try:\n        root = DefusedET.fromstring(xml_text.encode(\"utf-8\", \"replace\"))\n    except Exception as exc:  # noqa: BLE001 - a malformed filing is a data error\n        raise RuntimeError(f\"N-PORT document did not parse: {exc}\") from exc\n\n    form_data = _child(root, \"formData\")\n    gen_info = _child(form_data, \"genInfo\")\n    fund_info = _child(form_data, \"fundInfo\")\n    securities = _child(form_data, \"invstOrSecs\")\n\n    holdings = []\n    if securities is not None:\n        holdings = [\n            _parse_nport_holding(node)\n            for node in securities\n            if _local_name(node.tag) == \"invstOrSec\"\n        ]\n\n    return {\n        \"series_id\": _text_of(gen_info, \"seriesId\"),\n        \"series_name\": _text_of(gen_info, \"seriesName\"),\n        \"registrant\": _text_of(gen_info, \"regName\"),","sourceCodeStart":737,"sourceCodeEnd":773,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/etf_holdings_tool.py#L737-L773","documentation":"An individual N-PORT XML filing downloaded from EDGAR failed to parse with defusedxml, so it is treated as a malformed-filing data error. Usually the download was truncated or returned an HTML error page instead of the filing XML.","triggerScenarios":"Downloading an N-PORT primary document that is incomplete/truncated, sec.gov returning an error page for the document URL, or an encoding-mangled body that fromstring rejects even after utf-8 replace.","commonSituations":"Intermittent network drops mid-download; SEC rate limiting document GETs in tight loops; stale accession-number URLs after filings are amended/removed.","solutions":["Retry the specific filing download after throttling; verify the document URL opens in a browser","Check HTTP status and content-type before parsing, and skip+log filings that return HTML","Use the most recent accession when amendments supersede older documents"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import xml.etree.ElementTree as ET\n\ndef is_valid_xml(text: str) -> bool:\n    try:\n        ET.fromstring(text.encode(\"utf-8\", \"replace\"))\n        return True\n    except ET.ParseError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    holdings = _parse_nport(xml_text)\nexcept RuntimeError as exc:\n    if \"did not parse\" in str(exc):\n        xml_text = refetch(cik, accession)  # re-download with throttle\n        holdings = _parse_nport(xml_text)\n    else:\n        raise","preventionTips":["Check response status/Content-Type and body prefix (HTML vs XML) before parsing","Retry truncated downloads with backoff rather than parsing partial bodies","Skip and log malformed filings instead of aborting a whole batch"],"tags":["sec-edgar","xml-parsing","nport","network","python"],"backgroundTag":"xml-parse-error","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}