{"record":{"id":"0393a0d0e3d44746","repo":"sgl-project/sglang","slug":"allowed-media-domains-cannot-be-empty","errorCode":null,"errorMessage":"allowed media domains cannot be empty","messagePattern":"allowed media domains cannot be empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/utils/common.py","lineNumber":1526,"sourceCode":"        torch.xpu.manual_seed_all(seed)\n\n\n_mm_http_session = threading.local()\n\n_DEFAULT_MEDIA_URL_MAX_FILE_SIZE_MB = 64\n_MAX_MEDIA_URL_REDIRECTS = 5\n_MEDIA_URL_REDIRECT_STATUS_CODES = {301, 302, 303, 307, 308}\n_allowed_media_domains: frozenset[str] = frozenset()\n_media_url_max_file_size_bytes = _DEFAULT_MEDIA_URL_MAX_FILE_SIZE_MB * 1024 * 1024\n\n\ndef _normalize_media_domain(domain: str) -> str:\n    if not isinstance(domain, str):\n        raise ValueError(\"allowed media domains must be strings\")\n\n    domain = domain.strip().rstrip(\".\")\n    if not domain:\n        raise ValueError(\"allowed media domains cannot be empty\")\n    if \"://\" in domain or any(char in domain for char in \"/?#@\"):\n        raise ValueError(\n            f\"Invalid allowed media domain {domain!r}: provide a hostname only\"\n        )\n\n    # Brackets are URL syntax, not part of an IPv6 hostname.\n    if domain.startswith(\"[\") and domain.endswith(\"]\"):\n        domain = domain[1:-1]\n    try:\n        return str(ipaddress.ip_address(domain))\n    except ValueError:\n        if \":\" in domain:\n            raise ValueError(\n                f\"Invalid allowed media domain {domain!r}: ports are not supported\"\n            )\n\n    try:\n        normalized = domain.encode(\"idna\").decode(\"ascii\").lower()","sourceCodeStart":1508,"sourceCodeEnd":1544,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/utils/common.py#L1508-L1544","documentation":"After stripping whitespace and trailing dots, an allowed-media-domains entry became an empty string. The normalizer strips leading/trailing whitespace and a single trailing dot (DNS root form), so inputs like '   ' or '.' normalize to nothing and are rejected because an empty allowlist entry would match nothing and usually indicates a config typo.","triggerScenarios":"configure_media_url_security(allowed_media_domains=['', ' .', '.']) — entry reduces to empty after domain.strip().rstrip('.').","commonSituations":"Comma-splitting a user-supplied --allowed-media-domains value with trailing commas ('a.com,,b.com'); copy-paste config with stray dots; empty strings from YAML list entries.","solutions":["Strip and filter empty entries when parsing user input: [d for d in raw.split(',') if d.strip()]","Fix the typo in the config file / CLI flag","Validate the allowlist before server start"],"exampleFix":"# before\nconfigure_media_url_security(allowed_media_domains=['example.com', '', ''])\n# after\nconfigure_media_url_security(allowed_media_domains=[d for d in ['example.com', '', ''] if d.strip()])","handlingStrategy":"validation","validationCode":"domains = [d.strip().rstrip('.') for d in raw.split(',')]\ndomains = [d for d in domains if d]  # drop empties before configure()","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Filter empty strings when splitting user input","Lint config values at startup"],"tags":["validation","media","security","config"],"backgroundTag":"config-validation-failed","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}