{"record":{"id":"ffb59520df687ffe","repo":"microsoft/markitdown","slug":"unknown-feed-type","errorCode":null,"errorMessage":"Unknown feed type","messagePattern":"Unknown feed type","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"packages/markitdown/src/markitdown/converters/_rss_converter.py","lineNumber":99,"sourceCode":"                return \"atom\"\n        return None\n\n    def convert(\n        self,\n        file_stream: BinaryIO,\n        stream_info: StreamInfo,\n        **kwargs: Any,  # Options to pass to the converter\n    ) -> DocumentConverterResult:\n        self._kwargs = kwargs\n        doc = minidom.parse(file_stream)\n        feed_type = self._feed_type(doc)\n\n        if feed_type == \"rss\":\n            return self._parse_rss_type(doc)\n        elif feed_type == \"atom\":\n            return self._parse_atom_type(doc)\n        else:\n            raise ValueError(\"Unknown feed type\")\n\n    def _parse_atom_type(self, doc: Document) -> DocumentConverterResult:\n        \"\"\"Parse the type of an Atom feed.\n\n        Returns None if the feed type is not recognized or something goes wrong.\n        \"\"\"\n        root = doc.getElementsByTagName(\"feed\")[0]\n        title = self._get_data_by_tag_name(root, \"title\")\n        subtitle = self._get_data_by_tag_name(root, \"subtitle\")\n        entries = root.getElementsByTagName(\"entry\")\n        md_text = f\"# {title}\\n\"\n        if subtitle:\n            md_text += f\"{subtitle}\\n\"\n        for entry in entries:\n            entry_title = self._get_data_by_tag_name(entry, \"title\")\n            entry_summary = self._get_data_by_tag_name(entry, \"summary\")\n            entry_updated = self._get_data_by_tag_name(entry, \"updated\")\n            entry_content = self._get_data_by_tag_name(entry, \"content\")","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/microsoft/markitdown/blob/fd239d5d2be43d9b68329730206b9312c7d5a388/packages/markitdown/src/markitdown/converters/_rss_converter.py#L81-L117","documentation":"RssConverter.convert() re-parses the XML and asks _feed_type() whether the document has an <rss> root element or a <feed> root with at least one <entry>. If neither matches, it raises ValueError('Unknown feed type'). Notably, accepts() uses the same _feed_type check for .xml/candidate mimetypes, so in the normal MarkItDown pipeline this is near-unreachable — it chiefly occurs when calling the converter's convert() directly, or when the stream content differs between the accepts() sniff and the convert() parse (non-deterministic stream, concurrent read, seek position bugs).","triggerScenarios":"Directly invoking RssConverter().convert() on XML that is neither RSS nor Atom (e.g. a sitemap.xml, SOAP envelope, or generic XML with extension .rss forced via StreamInfo); passing a stream whose position/content changed between accepts() and convert(); an Atom-like document whose <feed> element exists but contains no <entry> children (the code requires at least one entry for 'atom').","commonSituations":"A file named feed.rss that is actually a sitemap or RDF feed (RSS 1.0 uses RDF, not <rss>); Atom feeds with zero entries; code that constructs StreamInfo manually (extension='.rss') for arbitrary XML to force the converter.","solutions":["Inspect the XML root element: valid RSS has <rss>, Atom has <feed> with <entry> children; anything else (including RSS 1.0/RDF) is not supported by this converter","Rename the file / fix the mimetype so generic XML converters handle it instead of RssConverter","For RSS 1.0 (RDF) feeds, convert them upstream to RSS 2.0 or Atom before passing to markitdown","If calling convert() directly, first call accepts() on the same stream (reset with seek(0)) and skip when it returns False"],"exampleFix":"# before\nconverter = RssConverter()\nresult = converter.convert(stream, StreamInfo(extension='.rss', mimetype='application/rss+xml'))  # ValueError on sitemap.xml\n\n# after\nstream.seek(0)\nif converter.accepts(stream, stream_info):\n    stream.seek(0)\n    result = converter.convert(stream, stream_info)\nelse:\n    result = None  # not an RSS/Atom feed; handle elsewhere","handlingStrategy":"type-guard","validationCode":"from defusedxml import minidom\n\ndef is_supported_feed(raw: bytes) -> bool:\n    try:\n        doc = minidom.parseString(raw)\n    except Exception:\n        return False\n    if doc.getElementsByTagName(\"rss\"):\n        return True\n    feeds = doc.getElementsByTagName(\"feed\")\n    return bool(feeds) and bool(feeds[0].getElementsByTagName(\"entry\"))","typeGuard":"def is_supported_feed_stream(stream) -> bool:\n    \"\"\"Narrow: True only for RSS (<rss>) or Atom (<feed> with <entry>) docs.\"\"\"\n    pos = stream.tell()\n    try:\n        doc = minidom.parse(stream)\n        if doc.getElementsByTagName(\"rss\"):\n            return True\n        f = doc.getElementsByTagName(\"feed\")\n        return bool(f) and bool(f[0].getElementsByTagName(\"entry\"))\n    except Exception:\n        return False\n    finally:\n        stream.seek(pos)","tryCatchPattern":"try:\n    result = MarkItDown().convert(\"feed.rss\")\nexcept ValueError as e:\n    if \"Unknown feed type\" in str(e):\n        logger.warning(\"document is RSS 1.0/RDF or generic XML; not supported\")","preventionTips":["Check the root element before converting: <rss> or <feed>+<entry> only; RSS 1.0/RDF feeds are unsupported","When calling RssConverter directly, always gate with accepts() on the same seek-reset stream","Name files accurately — do not label sitemaps/generic XML as .rss"],"tags":["rss","atom","xml","feed","validation"],"backgroundTag":null,"analyzedSha":"fd239d5d2be43d9b68329730206b9312c7d5a388","analyzedAt":"2026-08-14T15:47:51.745Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}