{"record":{"id":"1babbc14539fad25","repo":"xtekky/gpt4free","slug":"markitdown-requires-media-to-be-provided","errorCode":null,"errorMessage":"MarkItDown requires media to be provided.","messagePattern":"MarkItDown requires media to be provided\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"g4f/Provider/audio/MarkItDown.py","lineNumber":26,"sourceCode":"\n    has_markitdown = True\nexcept ImportError:\n    has_markitdown = False\n\nfrom ...typing import AsyncResult, Messages, MediaListType\nfrom ...tools.files import get_tempfile\nfrom ..base_provider import AsyncGeneratorProvider, ProviderModelMixin\n\n\nclass MarkItDown(AsyncGeneratorProvider, ProviderModelMixin):\n    working = has_markitdown\n\n    @classmethod\n    async def create_async_generator(\n        cls, model: str, messages: Messages, media: MediaListType = None, **kwargs\n    ) -> AsyncResult:\n        if media is None:\n            raise ValueError(\"MarkItDown requires media to be provided.\")\n        if not has_markitdown:\n            raise ImportError(\n                \"MarkItDown is not installed. Please install it with `pip install markitdown`.\"\n            )\n        md = MaItDo()\n        for file, filename in media:\n            text = None\n            try:\n                if isinstance(file, str) and file.startswith((\"http://\", \"https://\")):\n                    result = md.convert_url(file)\n                else:\n                    result = md.convert(\n                        file,\n                        stream_info=StreamInfo(filename=filename) if filename else None,\n                    )\n                if asyncio.iscoroutine(result.text_content):\n                    text = await result.text_content\n                else:","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/xtekky/gpt4free/blob/973504e1770928ed5fb82f43da528f441ad9ddc3/g4f/Provider/audio/MarkItDown.py#L8-L44","documentation":"ValueError from MarkItDown.create_async_generator when the media argument is None. MarkItDown converts documents to text; unlike chat providers it operates on files/URLs, so at least one media entry (file object, path, or URL) is required and the provider fails fast before checking whether markitdown is even installed.","triggerScenarios":"Routing a plain text-only chat request to the MarkItDown provider, i.e. no media supplied via the media parameter of the request.","commonSituations":"Misconfigured client with provider='MarkItDown' for normal chat; upload forms where the file field was left empty; orchestration code forgetting to attach media.","solutions":["Attach the document: pass media=[(open('doc.pdf','rb'), 'doc.pdf')] or a URL entry","Use a different provider for plain-text chat requests","Validate that media is non-empty before selecting MarkItDown as provider"],"exampleFix":"# before\nresp = await client.chat.completions.create(model='MarkItDown', messages=msgs)\n\n# after\nresp = await client.chat.completions.create(model='MarkItDown', messages=msgs, media=[('https://example.com/report.pdf', 'report.pdf')])","handlingStrategy":"validation","validationCode":"def has_media(media):\n    return bool(media) and len(media) > 0\n\nif provider_name == 'MarkItDown' and not has_media(media):\n    raise ValueError('MarkItDown requires an attachment')","typeGuard":"from g4f.typing import MediaListType\n\ndef is_non_empty_media(media: MediaListType | None) -> bool:\n    return media is not None and len(media) > 0","tryCatchPattern":"except ValueError as e:\n    if 'requires media' in str(e):\n        return 'No document attached.'  # user-facing message","preventionTips":["Require file selection in the UI before allowing the MarkItDown provider","Route text-only requests to chat providers, never document converters"],"tags":["markitdown","media-required","validation"],"backgroundTag":null,"analyzedSha":"973504e1770928ed5fb82f43da528f441ad9ddc3","analyzedAt":"2026-08-14T23:45:32.408Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}