mlflow/mlflow · error · MlflowException

Not a proper {scheme}:/ URI: {uri}. {entity_type} URIs must

Error message

Not a proper {scheme}:/ URI: {uri}. {entity_type} URIs must be of the form '{scheme}:/name/suffix' or '{scheme}:/name@alias' where suffix is a version, stage, or the string 'latest' and where alias is a registered {scheme[:-1]} alias. Only one of suffix or alias can be defined at a time.

What it means

`_parse_model_uri` validates that a models:/ or prompts:/ URI has the expected scheme before parsing. If urlparse reports a different scheme (or none), MLflow raises this 'not a proper URI' MlflowException because the string cannot be a model/prompt reference at all.

Source

Thrown at mlflow/store/artifact/utils/models.py:75


def _parse_model_uri(uri, scheme: str = "models") -> ParsedModelUri:
    """
    Returns a ParsedModelUri tuple. Since a models:/ or prompts:/ URI can only have one of
    {version, stage, 'latest', alias}, it will return
        - (id, None, None, None) to look for a specific model by ID,
        - (name, version, None, None) to look for a specific version,
        - (name, None, stage, None) to look for the latest version of a stage,
        - (name, None, None, None) to look for the latest of all versions.
        - (name, None, None, alias) to look for a registered model alias.

    Args:
        uri: The URI to parse (e.g., "models:/name/version" or "prompts:/name@alias")
        scheme: The expected URI scheme (default: "models", can be "prompts")
    """
    parsed = urllib.parse.urlparse(uri, allow_fragments=False)
    if parsed.scheme != scheme:
        raise MlflowException(_improper_model_uri_msg(uri, scheme))
    path = parsed.path
    if not path.startswith("/") or len(path) <= 1:
        raise MlflowException(_improper_model_uri_msg(uri, scheme))

    parts = path.lstrip("/").split("/")
    if len(parts) > 2 or parts[0].strip() == "":
        raise MlflowException(_improper_model_uri_msg(uri, scheme))

    if len(parts) == 2:
        name, suffix = parts
        if suffix.strip() == "":
            raise MlflowException(_improper_model_uri_msg(uri, scheme))
        # The URI is in the suffix format
        if suffix.isdigit():
            # The suffix is a specific version, e.g. "models:/AdsModel1/123"
            return ParsedModelUri(name=name, version=suffix)
        elif suffix.lower() == _MODELS_URI_SUFFIX_LATEST.lower() and scheme == "models":
            # The suffix is the 'latest' string (case insensitive), e.g. "models:/AdsModel1/latest"

View on GitHub (pinned to 6a27f2decc)

Solutions

  1. Prefix the reference with the correct scheme: 'models:/<name>/<version>' (or '@alias')
  2. If you have a storage path, load it directly (mlflow.pyfunc.load_model accepts local paths and file:///s3:/ URIs) — don't wrap it in models:/
  3. Check where the URI string comes from (config/env/DB) and validate it starts with 'models:/' before calling the API

Example fix

// before
m = mlflow.pyfunc.load_model("prod-model")
// after
m = mlflow.pyfunc.load_model("models:/prod-model@champion")
Defensive patterns

Strategy: validation

Validate before calling

def is_model_uri(u: str) -> bool:
    return isinstance(u, str) and u.startswith("models:/")

Type guard

def is_model_uri(u: object) -> bool:
    return isinstance(u, str) and u.startswith("models:/")

Try / catch

from mlflow.exceptions import MlflowException
try:
    model = mlflow.pyfunc.load_model(uri)
except MlflowException:
    model = mlflow.pyfunc.load_model(artifact_uri)  # fallback to storage path

Prevention

When it happens

Trigger: Passing a URI like 's3://bucket/model', a bare 'my-model' with no scheme, 'model:/name/1' (typo), or a Windows-style 'C:\models\x' to load_model / _parse_model_id_if_present / get_model_name_and_version when scheme='models' or 'prompts' is expected.

Common situations: Passing an artifact path or local directory where a models:/ URI is required; environment-specific config that injects a storage URI instead of a registry URI; forgetting the 'models:' prefix; double slashes like 'models://name/1' making the scheme parse differently.

Related errors


AI-assisted analysis of mlflow/mlflow@6a27f2decc (2026-08-29). Data as JSON: /api/errors/8fad59eef877d623. Report an issue: GitHub.