mlflow/mlflow · error · MlflowException
Invalid webhook URL {url!r}: {e!r}
Error message
Invalid webhook URL {url!r}: {e!r} What it means
Raised by _validate_webhook_url when urllib.parse.urlparse raises ValueError on the given URL string, meaning the URL is syntactically unparseable (typically malformed IPv6 literals like 'http://[::1' or characters outside what urlparse accepts). MLflow wraps that underlying ValueError into an MlflowException.invalid_parameter_value with the original URL and error repr.
Source
Thrown at mlflow/utils/validation.py:1151
_validate_mcp_list_max_length(tools, field_name, _MAX_MCP_TOOLS_PER_LIST)
def _validate_webhook_url(url: str) -> None:
if not isinstance(url, str):
raise MlflowException.invalid_parameter_value(
f"Webhook URL must be a string, got {type(url).__name__!r}"
)
if not url.strip():
raise MlflowException.invalid_parameter_value(
f"Webhook URL cannot be empty or just whitespace: {url!r}"
)
try:
parsed_url = urllib.parse.urlparse(url)
except ValueError as e:
raise MlflowException.invalid_parameter_value(f"Invalid webhook URL {url!r}: {e!r}") from e
schemes = _MLFLOW_WEBHOOK_ALLOWED_SCHEMES.get()
if parsed_url.scheme not in schemes:
raise MlflowException.invalid_parameter_value(
f"Invalid webhook URL scheme: {parsed_url.scheme!r}. "
f"Allowed schemes are: {', '.join(schemes)}."
)
hostname = parsed_url.hostname
if not hostname:
raise MlflowException.invalid_parameter_value(
f"Webhook URL must include a hostname: {url!r}"
)
if not _MLFLOW_WEBHOOK_ALLOW_PRIVATE_IPS.get():
_validate_hostname_resolves_to_public_ips(hostname, "Webhook URL")
def _validate_webhook_events(events: list[WebhookEvent]) -> None:View on GitHub (pinned to 6a27f2decc)
Solutions
- Inspect the URL in the message for structural typos (e.g. unclosed '[' in IPv6 hosts) and fix it to a well-formed URL.
- Validate locally first: python -c "import urllib.parse; urllib.parse.urlparse('<your url>')" to reproduce and debug before calling the API.
- If building URLs programmatically, use urllib.parse.urlunparse or urlencode to construct them safely.
- If the malformed URL is already stored, call update_webhook with a corrected URL to replace it.
Example fix
// before
url = "https://hooks.example.com/notify?data={a b}" # malformed
client.create_webhook(name="w", url=url, events=[...])
// after
import urllib.parse
url = urllib.parse.urlunparse(("https", "hooks.example.com", "/notify", "",
urllib.parse.urlencode({"data": "a b"}), ""))
client.create_webhook(name="w", url=url, events=[...]) Defensive patterns
Strategy: validation
Validate before calling
import urllib.parse
def validate_url_parseable(url):
try:
urllib.parse.urlparse(url)
except ValueError as e:
raise ValueError(f"Malformed webhook URL {url!r}: {e}") from e Type guard
def is_parseable_url(url):
if not isinstance(url, str):
return False
try:
urllib.parse.urlparse(url)
return True
except ValueError:
return False Try / catch
from mlflow.exceptions import MlflowException
try:
client.create_webhook(name=name, url=url, events=events)
except MlflowException as e:
if "Invalid webhook URL" in str(e):
url = fix_or_prompt_for_url(url) # e.g. repair IPv6 brackets / re-encode
client.create_webhook(name=name, url=url, events=events)
else:
raise Prevention
- Run urlparse on URLs before storing or sending them to catch syntax errors early.
- Build URLs with urllib.parse.urlunparse/urlencode instead of string concatenation.
- Beware IPv6 literals: brackets must be balanced, e.g. http://[::1]:8080/hook.
- Round-trip check stored webhook URLs (parse then unparse) during config load to catch corruption.
When it happens
Trigger: Calling create_webhook, update_webhook, or test_validate_webhook_url with a structurally malformed URL such as 'http://[::1' (unclosed IPv6 bracket) or a URL containing characters that make urlparse raise; _send_webhook_request validating a stored URL that was corrupted.
Common situations: Hand-edited webhook URLs with a typo (missing bracket, stray control character); programmatic URL construction with unescaped/unencoded parts; URLs stored before validation in older versions then hit during delivery; copying a URL that got truncated or mangled by a shell.
Related errors
- Webhook URL must be a string, got {type(url).__name__!r}
- Webhook URL cannot be empty or just whitespace: {url!r}
- At least one location must be specified for searching traces
- The `requestPreview` parameter must be a string.
- The `responsePreview` parameter must be a string.
AI-assisted analysis of mlflow/mlflow@6a27f2decc (2026-08-29).
Data as JSON: /api/errors/aae2c2e1f95b9e93.
Report an issue: GitHub.