mlflow/mlflow · error · MlflowException

INVALID_PARAMETER_VALUE

INVALID_PARAMETER_VALUE

Error message

Exactly one of {param1_name} or {param2_name} must be provided

What it means

_validate_one_of enforces that exactly one of two mutually exclusive lookup parameters (e.g. name vs id/uid) is supplied. If both are provided, or both are None, the gateway store lookup methods (get_secret_info, get_gateway_model_definition, get_gateway_endpoint) raise MlflowException with INVALID_PARAMETER_VALUE. This prevents ambiguous lookups.

Source

Thrown at mlflow/store/tracking/gateway/sqlalchemy_mixin.py:110

    KEKManager,
    _encrypt_secret,
    _mask_secret_value,
)
from mlflow.utils.mlflow_tags import (
    MLFLOW_EXPERIMENT_IS_GATEWAY,
    MLFLOW_EXPERIMENT_SOURCE_ID,
    MLFLOW_EXPERIMENT_SOURCE_TYPE,
)
from mlflow.utils.search_utils import SearchUtils
from mlflow.utils.time import get_current_time_millis


def _validate_one_of(
    param1_name: str, param1_value: Any, param2_name: str, param2_value: Any
) -> None:
    """Validate that exactly one of two parameters is provided."""
    if (param1_value is None) == (param2_value is None):
        raise MlflowException(
            f"Exactly one of {param1_name} or {param2_name} must be provided",
            error_code=INVALID_PARAMETER_VALUE,
        )


_TARGETED_BUDGET_SCOPES = (BudgetTargetScope.ENDPOINT.value,)


def _normalize_budget_target_value(
    target_scope: str | None, target_value: str | None
) -> str | None:
    """Enforce the budget policy target_value/target_scope invariant at the store layer.

    ENDPOINT-scoped policies must carry a ``target_value`` (the ID of the endpoint to
    match; without one the policy silently never matches any request and thus never
    enforces). Policies with any other scope must not carry one, so a stray
    ``target_value`` is dropped. This mirrors the REST handler validation so
    direct/programmatic store callers cannot persist a policy that violates the

View on GitHub (pinned to 6a27f2decc)

Solutions

  1. Pass exactly one of the two parameters — delete the redundant one from the call.
  2. If you have both values available, choose the one the API prefers (usually the stable id) and drop the other.
  3. When values come from user input/config, validate before calling: (name is None) != (id is None) must be True, otherwise raise a clear upstream error.

Example fix

// before
store.get_gateway_endpoint(endpoint_id='e123', endpoint_name='my-endpoint')  # both set -> error

// after
store.get_gateway_endpoint(endpoint_name='my-endpoint')  # exactly one provided
Defensive patterns

Strategy: validation

Validate before calling

def validate_exactly_one(**kwargs):
    provided = [k for k, v in kwargs.items() if v is not None]
    if len(provided) != 1:
        raise ValueError(f'Exactly one of {list(kwargs)} must be provided, got: {provided or "none"}')

# usage before the store call:
# validate_exactly_one(endpoint_id=endpoint_id, endpoint_name=endpoint_name)

Type guard

def has_exactly_one(a, b) -> bool:
    return (a is None) != (b is None)

Try / catch

from mlflow.exceptions import MlflowException
try:
    ep = store.get_gateway_endpoint(endpoint_id=endpoint_id, endpoint_name=endpoint_name)
except MlflowException as e:
    if 'must be provided' in str(e):
        raise ValueError('Pass exactly one of endpoint_id or endpoint_name to get_gateway_endpoint.') from e
    raise

Prevention

When it happens

Trigger: Calling get_secret_info, get_gateway_model_definition, or get_gateway_endpoint with both identifier arguments set (e.g. secret_id and secret_name) or with both omitted (None).

Common situations: Refactored code that kept an old id argument while adding a name argument; dynamic callers building kwargs where an unset variable defaults to None so neither key is populated; copy-pasted lookup calls that pass both fields 'to be safe'.

Related errors


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