{"record":{"id":"03ee0911191d90f2","repo":"docling-project/docling","slug":"unsupported-url-scheme-scheme-only-http-a","errorCode":null,"errorMessage":"Unsupported URL scheme: '{scheme}'. Only http:// and https:// are supported.","messagePattern":"Unsupported URL scheme: '(.+?)'\\. Only http:// and https:// are supported\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"docling/service_client/client.py","lineNumber":533,"sourceCode":"            \"tar.gz\" if lowered.endswith(\".tar.gz\") else Path(name).suffix[1:].lower()\n        )\n        if extension in self._extension_to_format:\n            return self._extension_to_format[extension]\n        return InputFormat.PDF\n\n    def _normalize_source(\n        self, source: SourceType\n    ) -> Path | HttpSourceRequest | DocumentStream:\n        if isinstance(source, (Path, HttpSourceRequest, DocumentStream)):\n            return source\n        try:\n            http_url = TypeAdapter(AnyHttpUrl).validate_python(source)\n            return HttpSourceRequest(url=str(http_url), headers={})\n        except ValidationError:\n            if \"://\" in source:\n                scheme = source.split(\"://\", 1)[0].lower()\n                if scheme not in (\"http\", \"https\"):\n                    raise ValueError(\n                        f\"Unsupported URL scheme: '{scheme}'. Only http:// and https:// are supported.\"\n                    )\n            return TypeAdapter(Path).validate_python(source)\n\n    @staticmethod\n    def _validate_concurrency(value: int, *, name: str) -> int:\n        if value < 1 or value > MAX_CONCURRENCY_LIMIT:\n            raise ValueError(\n                f\"{name} must be between 1 and {MAX_CONCURRENCY_LIMIT}, got {value}.\"\n            )\n        return value\n\n    @staticmethod\n    def _normalize_exception(exc: BaseException) -> Exception:\n        if isinstance(exc, Exception):\n            return exc\n        return RuntimeError(str(exc))\n","sourceCodeStart":515,"sourceCodeEnd":551,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/service_client/client.py#L515-L551","documentation":"When _normalize_source receives a string that fails AnyHttpUrl validation but contains '://', the client extracts the scheme and only accepts http/https; anything else (ftp, s3, file, gs, ...) raises ValueError with this message. Strings without '://' fall through to local Path validation, so this error specifically guards remote-source URLs with unsupported schemes.","triggerScenarios":"Passing 'ftp://server/file.pdf', 's3://bucket/doc.pdf', or 'file:///tmp/doc.pdf' as a source to convert(); AnyHttpUrl rejecting a malformed http URL (e.g. missing host) can also surface here; copy-pasting cloud-storage presigned URLs with their native scheme.","commonSituations":"Feeding S3/GCS/Azure URLs directly instead of downloading first or using an http(s) presigned URL; scripts that accept arbitrary URI inputs; Windows drive-letter strings that parse oddly.","solutions":["Download non-http sources (s3://, ftp://, gs://) yourself and pass a local Path, or generate an https presigned URL.","For http(s) URLs, ensure they are well-formed (scheme + host).","For local files, pass a pathlib.Path or a plain path string without '://'."],"exampleFix":"# before\nresult = client.convert('s3://my-bucket/doc.pdf')  # ValueError\n\n# after\nimport boto3, pathlib\ns3 = boto3.client('s3')\ns3.download_file('my-bucket', 'doc.pdf', '/tmp/doc.pdf')\nresult = client.convert(pathlib.Path('/tmp/doc.pdf'))","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\n\ndef source_ok(s: str) -> bool:\n    if '://' not in s:\n        return True  # treated as local path\n    return urlparse(s).scheme in ('http', 'https')","typeGuard":"def is_http_url(s: str) -> bool:\n    from urllib.parse import urlparse\n    p = urlparse(s)\n    return p.scheme in ('http', 'https') and bool(p.netloc)","tryCatchPattern":"try:\n    result = client.convert(url)\nexcept ValueError as e:\n    if 'Unsupported URL scheme' in str(e):\n        local = download_to_temp(url)\n        result = client.convert(local)","preventionTips":["Convert s3://gs://ftp:// sources to local Paths or https presigned URLs first.","Pass local files as pathlib.Path, not file:// URIs."],"tags":["service-client","url","scheme","validation"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}