{"record":{"id":"99a88205a816eaa2","repo":"docling-project/docling","slug":"cannot-resolve-hostname-hostname","errorCode":null,"errorMessage":"Cannot resolve hostname: {hostname}","messagePattern":"Cannot resolve hostname: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"docling/backend/utils/image_resource_loader.py","lineNumber":63,"sourceCode":"\n    Raises:\n        ValueError: If the URL has no hostname, the hostname cannot be\n            resolved, or it resolves to a restricted (non-global) IP address.\n    \"\"\"\n    parsed = urlparse(url)\n    hostname = parsed.hostname\n\n    if not hostname:\n        raise ValueError(\"URL must contain a valid hostname\")\n\n    try:\n        ip = ipaddress.ip_address(hostname)\n    except ValueError:\n        try:\n            ip_str = socket.gethostbyname(hostname)\n            ip = ipaddress.ip_address(ip_str)\n        except (socket.gaierror, socket.herror) as e:\n            raise ValueError(f\"Cannot resolve hostname: {hostname}\") from e\n\n    if not (\n        ip.is_global\n        and not (\n            ip.is_private\n            or ip.is_loopback\n            or ip.is_link_local\n            or ip.is_reserved\n            or ip.is_multicast\n            or ip.is_unspecified\n        )\n    ):\n        raise ValueError(f\"Access to restricted IP address not allowed: {ip}\")\n\n\nclass ImageResourceLoader:\n    \"\"\"Resolve and load image resources for declarative document backends.\n","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/backend/utils/image_resource_loader.py#L45-L81","documentation":"ValueError raised when the URL's hostname is not a literal IP and socket.gethostbyname() fails with gaierror/herror — i.e. DNS cannot resolve it. Part of validate_url_safety; the original socket error is chained. Resolution happens before the restricted-IP check so that hostnames pointing at internal ranges are still caught.","triggerScenarios":"Document references an image at a hostname like https://nonexistent.invalid/x.png (NXDOMAIN), a name only resolvable on an internal DNS the runner lacks, or a typo like 'https://exmaple.com/logo.png'.","commonSituations":"Converting HTML crawled from intranets on machines without that DNS; offline environments blocking outbound DNS; expired external image hosts.","solutions":["Check resolution where docling runs: dig +short example.com or python -c \"import socket; socket.gethostbyname('example.com')\".","If offline, disable remote fetch and pre-download images (or enable_local_fetch with a local base_path).","Fix typo'd hostnames in the source document.","Catch ValueError to skip unresolvable images and continue conversion."],"exampleFix":"# before\nloader.load_image_data('https://exmaple.com/logo.png', base)  # Cannot resolve hostname\n\n# after\nimport socket\nhost = 'exmaple.com'\ntry:\n    socket.gethostbyname(host)\n    data = loader.load_image_data(f'https://{host}/logo.png', base)\nexcept socket.gaierror:\n    data = None  # skip broken image","handlingStrategy":"validation","validationCode":"import socket\nfrom urllib.parse import urlparse\nhost = urlparse(url).hostname\nif host:\n    try:\n        socket.gethostbyname(host)\n    except (socket.gaierror, socket.herror):\n        raise ValueError(f'cannot resolve {host}; skip or fix URL')","typeGuard":null,"tryCatchPattern":"try:\n    data = loader.load_image_data(src, base)\nexcept ValueError as e:\n    if 'Cannot resolve hostname' in str(e):\n        data = None  # degrade gracefully, skip image\n    else:\n        raise","preventionTips":["Verify DNS works in the runtime that fetches images, not your laptop","Disable remote fetch in offline runs and pre-localize assets","Log skipped-hostname errors to find dead links in source documents"],"tags":["ssrf","dns","network","images"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}