{"record":{"id":"4b40e86be9a64dab","repo":"HKUDS/Vibe-Trading","slug":"edgar-filing-feed-did-not-parse-exc","errorCode":null,"errorMessage":"EDGAR filing feed did not parse: {exc}","messagePattern":"EDGAR filing feed did not parse: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/etf_holdings_tool.py","lineNumber":539,"sourceCode":"    Raises:\n        requests.RequestException: Network failure or non-2xx status.\n    \"\"\"\n    body = _sec_get_text(\n        _SEC_BROWSE_URL,\n        params={\n            \"action\": \"getcompany\",\n            \"CIK\": series_id,\n            \"type\": \"NPORT-P\",\n            \"dateb\": \"\",\n            \"owner\": \"include\",\n            \"count\": str(_SEC_FILING_COUNT),\n            \"output\": \"atom\",\n        },\n    )\n    try:\n        root = DefusedET.fromstring(body.encode(\"utf-8\", \"replace\"))\n    except Exception as exc:  # noqa: BLE001 - a malformed feed is a data error\n        raise RuntimeError(f\"EDGAR filing feed did not parse: {exc}\") from exc\n\n    filings: list[dict[str, Any]] = []\n    for element in root.iter():\n        if _local_name(element.tag) != \"content\":\n            continue\n        fields = {_local_name(c.tag): (c.text or \"\").strip() for c in element}\n        accession = fields.get(\"accession-number\")\n        if not accession:\n            continue\n        filings.append(\n            {\n                \"form\": fields.get(\"filing-type\") or None,\n                \"accession\": accession,\n                \"filing_date\": fields.get(\"filing-date\") or None,\n            }\n        )\n    return filings\n","sourceCodeStart":521,"sourceCodeEnd":557,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/etf_holdings_tool.py#L521-L557","documentation":"The EDGAR atom filing feed (browse-edgar filer feed, output=atom) was fetched but its body is not parseable XML — defusedxml raised while parsing. The raw body is likely an HTML error page (403/404 rate-limit page) rather than the atom feed.","triggerScenarios":"Calling _holdings_us for a CIK whose N-PORT feed request returns SEC's HTML 'too many requests' or error page; proxy/mitm rewriting responses; truncated response bodies.","commonSituations":"Hitting SEC's 10-req/sec fair-access rate limit in loops; CI runners sharing an IP; sec.gov blocking default client user-agents; transient 5xx bodies.","solutions":["Add throttling (>=1 req/sec) and retry with backoff around the feed fetch","Send a declared User-Agent like 'SampleCo admin@example.com' per SEC policy","Inspect the raw body just before the raise to confirm which error page SEC returned","Cache feed results per CIK to avoid repeated hits"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import xml.etree.ElementTree as ET\n\ndef feed_looks_like_atom(body: str) -> bool:\n    try:\n        ET.fromstring(body.encode(\"utf-8\", \"replace\"))\n        return True\n    except ET.ParseError:\n        return False","typeGuard":null,"tryCatchPattern":"for attempt in range(4):\n    try:\n        filings = _us_nport_filings(cik)\n        break\n    except RuntimeError as exc:\n        if \"feed did not parse\" in str(exc) and attempt < 3:\n            time.sleep(1.5 ** attempt)\n            continue\n        raise","preventionTips":["Rate-limit EDGAR calls and send a compliant User-Agent","Cache atom feed responses per CIK+period to avoid repeat fetches","Treat HTML bodies (starts with '<!DOCTYPE html') as rate-limit signals and back off before parsing"],"tags":["network","sec-edgar","xml-parsing","rate-limit","python"],"backgroundTag":"xml-parse-error","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}