{"record":{"id":"56703039c540dc08","repo":"microsoft/markitdown","slug":"not-a-file-url-file-uri","errorCode":null,"errorMessage":"Not a file URL: {file_uri}","messagePattern":"Not a file URL: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"packages/markitdown/src/markitdown/_uri_utils.py","lineNumber":12,"sourceCode":"import base64\nimport os\nfrom typing import Tuple, Dict\nfrom urllib.request import url2pathname\nfrom urllib.parse import urlparse, unquote_to_bytes\n\n\ndef file_uri_to_path(file_uri: str) -> Tuple[str | None, str]:\n    \"\"\"Convert a file URI to a local file path\"\"\"\n    parsed = urlparse(file_uri)\n    if parsed.scheme != \"file\":\n        raise ValueError(f\"Not a file URL: {file_uri}\")\n\n    netloc = parsed.netloc if parsed.netloc else None\n    path = os.path.abspath(url2pathname(parsed.path))\n    return netloc, path\n\n\ndef parse_data_uri(uri: str) -> Tuple[str | None, Dict[str, str], bytes]:\n    if not uri.startswith(\"data:\"):\n        raise ValueError(\"Not a data URI\")\n\n    header, _, data = uri.partition(\",\")\n    if not _:\n        raise ValueError(\"Malformed data URI, missing ',' separator\")\n\n    meta = header[5:]  # Strip 'data:'\n    parts = meta.split(\";\")\n\n    is_base64 = False","sourceCodeStart":1,"sourceCodeEnd":30,"githubUrl":"https://github.com/microsoft/markitdown/blob/fd239d5d2be43d9b68329730206b9312c7d5a388/packages/markitdown/src/markitdown/_uri_utils.py#L1-L30","documentation":"file_uri_to_path() parses the URI with urlparse and requires scheme == 'file'; anything else raises ValueError with the offending URI echoed. Inside convert_uri() it is only called after a startswith('file:') check, so end users normally see this only when calling the utility directly.","triggerScenarios":"Directly calling markitdown._uri_utils.file_uri_to_path('https://x/f.txt') or ('data:text/plain,hi') — i.e. passing a non-file URI to a function dedicated to file URIs.","commonSituations":"Reusing the internal helper in custom pipelines that route URIs by scheme, or calling it on unvalidated user input containing http/data/scheme-less strings.","solutions":["Branch on scheme first: only call file_uri_to_path when uri.startswith('file:')","Use convert_uri() instead of the helper — it performs the routing for you","Validate with urlparse(uri).scheme == 'file' before calling"],"exampleFix":"# before\nfile_uri_to_path(\"https://example.com/a.txt\")  # ValueError\n\n# after\nfrom urllib.parse import urlparse\nif urlparse(uri).scheme == \"file\":\n    netloc, path = file_uri_to_path(uri)","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\n\nassert urlparse(uri).scheme == \"file\"","typeGuard":null,"tryCatchPattern":"from markitdown._uri_utils import file_uri_to_path\n\ntry:\n    netloc, path = file_uri_to_path(uri)\nexcept ValueError:\n    # not a file URI; route to the appropriate handler\n    raise","preventionTips":["Prefer the public convert_uri() over internal _uri_utils helpers","Centralize scheme-based routing in one place instead of scattering direct helper calls"],"tags":["uri","internal-util","validation"],"backgroundTag":null,"analyzedSha":"fd239d5d2be43d9b68329730206b9312c7d5a388","analyzedAt":"2026-08-14T15:47:51.745Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}