mlflow/mlflow · error · MlflowException
PERMISSION_DENIED
PERMISSION_DENIED
Error message
Permission denied.
What it means
MLflow raises PERMISSION_DENIED when auto-creation of the parent MCP server registry entry is not permitted during create_mcp_server_version. If the parent did not exist and was created on the fly, but the caller lacks update permission on the (re-checked) existing parent, the operation is denied to prevent privilege escalation via auto-create.
Source
Thrown at mlflow/server/mcp_server_api.py:564
def _ensure_version_create_parent_access(
store, name: str, username: str | None, request: Request
) -> None:
if not getattr(request.state, "mcp_server_parent_auto_created", False):
return
try:
store.create_mcp_server(name=name, created_by=username)
except MlflowException as e:
if e.error_code != ErrorCode.Name(RESOURCE_ALREADY_EXISTS):
raise
request.state.mcp_server_parent_auto_created = False
can_update_existing = getattr(
request.state, "mcp_server_can_update_existing_recheck", lambda: False
)
if not can_update_existing():
raise MlflowException("Permission denied.", error_code=PERMISSION_DENIED)
def _update_mcp_access_endpoint_kwargs(
server_name: str, endpoint_id: str, body: UpdateMCPAccessEndpointRequest
) -> dict[str, Any]:
kwargs: dict[str, Any] = {"server_name": server_name, "endpoint_id": endpoint_id}
provided_fields = body.model_fields_set
for field_name in ("server_version", "server_alias", "url"):
if field_name in provided_fields:
kwargs[field_name] = getattr(body, field_name)
if "transport_type" in provided_fields:
kwargs["transport_type"] = (
None if body.transport_type is None else _parse_transport_type(body.transport_type)
)
return kwargs
mcp_server_router = APIRouter(tags=["MCP Server Registry"])View on GitHub (pinned to 6a27f2decc)
Solutions
- Have an admin grant the user UPDATE permission on the parent MCP server.
- Retry the request - if the parent now exists and you have access, the create may succeed via the normal path.
- Create the parent MCP server explicitly with adequate permissions before creating versions.
- Check workspace/registry permission configuration to ensure the role includes update on existing servers.
Defensive patterns
Strategy: try-catch
Validate before calling
import mlflow
from mlflow.exceptions import MlflowException
def can_create_version(name: str) -> bool:
try:
mlflow.mcp_server.get_mcp_server(name)
return True
except MlflowException:
return False # will need auto-create/update permission Type guard
def has_update_permission(server) -> bool:
return getattr(server, "can_update", False) or getattr(server, "user_can_update", False) Try / catch
from mlflow.exceptions import MlflowException
try:
client.create_mcp_server_version(name, body)
except MlflowException as e:
if e.error_code == "PERMISSION_DENIED":
request_admin_grant("UPDATE", resource=name) # escalate via admin, not retry-spam Prevention
- Verify the caller's permission level on the parent server before automated version creation
- Avoid concurrent first-time creates of the same server; create the parent once up front
- Use a service principal with both create and update scopes for CI pipelines
When it happens
Trigger: create_mcp_server_version where the parent server record does not exist (auto-create path runs), then the can_update_existing recheck finds a parent was created concurrently by another request and the current user lacks update permission on it.
Common situations: Race between two clients creating the same server version simultaneously; users with create-but-not-update permissions calling version creation for a server they do not own.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Failed to get Databricks App '{app_name}'. Make sure the app
- Got unexpected error response when checking whether file {db
- Cannot downgrade workspace permissions migration because dro
- INVALID_PARAMETER_VALUE
- INVALID_PARAMETER_VALUE
AI-assisted analysis of mlflow/mlflow@6a27f2decc (2026-08-29).
Data as JSON: /api/errors/7f8c8e24da729460.
Report an issue: GitHub.