{"record":{"id":"5dbb5600353b2d1a","repo":"microsoft/markitdown","slug":"unsupported-file-uri-uri-netloc-must-be-empty","errorCode":null,"errorMessage":"Unsupported file URI: {uri}. Netloc must be empty or localhost.","messagePattern":"Unsupported file URI: (.+?)\\. Netloc must be empty or localhost\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"packages/markitdown/src/markitdown/_markitdown.py","lineNumber":445,"sourceCode":"\n    def convert_uri(\n        self,\n        uri: str,\n        *,\n        stream_info: Optional[StreamInfo] = None,\n        file_extension: Optional[str] = None,  # Deprecated -- use stream_info\n        mock_url: Optional[\n            str\n        ] = None,  # Mock the request as if it came from a different URL\n        **kwargs: Any,\n    ) -> DocumentConverterResult:\n        uri = uri.strip()\n\n        # File URIs\n        if uri.startswith(\"file:\"):\n            netloc, path = file_uri_to_path(uri)\n            if netloc and netloc != \"localhost\":\n                raise ValueError(\n                    f\"Unsupported file URI: {uri}. Netloc must be empty or localhost.\"\n                )\n            return self.convert_local(\n                path,\n                stream_info=stream_info,\n                file_extension=file_extension,\n                url=mock_url,\n                **kwargs,\n            )\n        # Data URIs\n        elif uri.startswith(\"data:\"):\n            mimetype, attributes, data = parse_data_uri(uri)\n\n            base_guess = StreamInfo(\n                mimetype=mimetype,\n                charset=attributes.get(\"charset\"),\n            )\n            if stream_info is not None:","sourceCodeStart":427,"sourceCodeEnd":463,"githubUrl":"https://github.com/microsoft/markitdown/blob/fd239d5d2be43d9b68329730206b9312c7d5a388/packages/markitdown/src/markitdown/_markitdown.py#L427-L463","documentation":"In convert_uri(), URIs starting with file: are parsed with file_uri_to_path(); RFC 8089 allows an authority (netloc) only for localhost. Any other host in the authority (file://server/share.docx) is rejected with this ValueError because the library only reads local filesystem paths.","triggerScenarios":"md.convert_uri('file://nas/share/report.docx') or any file URI whose netloc is a hostname other than localhost (note: file://localhost/... IS accepted).","commonSituations":"Copy-pasting UNC paths as file:// URIs from Windows Explorer or Office hyperlinks, or generating file URIs from network mounts without normalizing the authority.","solutions":["Use a three-slash local URI: file:///mnt/nas/share/report.docx (mount the share locally first)","Use file://localhost/path only if you truly mean the local machine","Or skip the URI and pass the local path directly: md.convert('/mnt/nas/share/report.docx')"],"exampleFix":"# before\nmd.convert_uri(\"file://nas/report.docx\")  # ValueError\n\n# after\nmd.convert_uri(\"file:///mnt/nas/report.docx\")\n# or\nmd.convert(\"/mnt/nas/report.docx\")","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\n\ndef is_local_file_uri(uri: str) -> bool:\n    p = urlparse(uri)\n    return p.scheme == \"file\" and p.netloc in (\"\", \"localhost\")","typeGuard":null,"tryCatchPattern":"try:\n    result = md.convert_uri(uri)\nexcept ValueError as e:\n    if \"Netloc must be empty or localhost\" in str(e):\n        raise ValueError(f\"Remote file URI not supported; mount it locally: {uri}\") from e\n    raise","preventionTips":["Normalize file URIs to three-slash form (file:///abs/path) at ingestion","Mount network shares locally instead of passing UNC-style file://host/ URIs"],"tags":["uri","file-uri","validation"],"backgroundTag":null,"analyzedSha":"fd239d5d2be43d9b68329730206b9312c7d5a388","analyzedAt":"2026-08-14T15:47:51.745Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}