hiyouga/LlamaFactory · error · HTTPException
Invalid URL hostname.
Error message
Invalid URL hostname.
What it means
Raised as HTTP 400 by check_ssrf_url when urlparse(url).hostname is empty — the URL parses but has no host component. This catches malformed URLs like 'http://', 'https:///path', or scheme-only strings before getaddrinfo would be called with None.
Source
Thrown at src/llamafactory/api/common.py:79
if not real_path.startswith(safe_path):
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, detail="File access is restricted to the safe media directory."
)
except Exception:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid or inaccessible file path.")
def check_ssrf_url(url: str) -> None:
"""Checks if a given URL is vulnerable to SSRF. Raises HTTPException if unsafe."""
try:
parsed_url = urlparse(url)
if parsed_url.scheme not in ["http", "https"]:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Only HTTP/HTTPS URLs are allowed.")
hostname = parsed_url.hostname
if not hostname:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid URL hostname.")
ip_info = socket.getaddrinfo(hostname, parsed_url.port)
ip_address_str = ip_info[0][4][0]
ip = ipaddress.ip_address(ip_address_str)
if not ip.is_global:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Access to private or reserved IP addresses is not allowed.",
)
except socket.gaierror:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, detail=f"Could not resolve hostname: {parsed_url.hostname}"
)
except Exception as e:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"Invalid URL: {e}")
View on GitHub (pinned to f28afaf635)
Solutions
- Fix the URL to include a real hostname, e.g. https://example.com/img.png.
- Check templating/interpolation that builds media URLs for empty variables.
- Add client-side validation that new URL(url).hostname is non-empty before sending.
Example fix
// before
url: `${process.env.MEDIA_HOST}/img.png` // MEDIA_HOST unset -> https:///img.png
// after
const host = process.env.MEDIA_HOST; if (!host) throw new Error('MEDIA_HOST required');
url: `${host}/img.png` Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
def has_host(u):
return bool(urlparse(u).hostname)
assert has_host(url), f"URL missing host: {url!r}" Type guard
const hasHost = (u) => Boolean(new URL(u).hostname);
Try / catch
catch (e) { if (e.status === 400 && e.detail === 'Invalid URL hostname.') { fail fast on templating bug that produced the URL; } throw e; } Prevention
- Assert interpolated env vars are non-empty before building URLs.
- Add URL sanity checks to config linting.
- Test URL builders with unset-variable cases.
When it happens
Trigger: url = 'http://', 'https:///img.png', or a URL where the host was stripped by templating bugs (e.g. `${HOST}/img.png` with HOST unset).
Common situations: Environment-variable interpolation leaving an empty host; string concatenation bugs dropping the host; placeholder URLs left in config during testing.
Related errors
- Only HTTP/HTTPS URLs are allowed.
- Invalid URL: {e}
- Could not resolve hostname: {parsed_url.hostname}
- Invalid or inaccessible file path.
- Access to private or reserved IP addresses is not allowed.
AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14).
Data as JSON: /api/errors/ed9a1174762f62de.
Report an issue: GitHub.