-
Notifications
You must be signed in to change notification settings - Fork 118
Description
Summary
When exporting registered models using the mlflow-export-import tool against a standard MLflow Tracking Server secured with Basic Authentication, the export fails with:
401 Unauthorized β You are not authenticated.
This happens even though experiments and runs export successfully, and environment variables
MLFLOW_TRACKING_USERNAME and MLFLOW_TRACKING_PASSWORD are set correctly.
The root cause is that BasicAuth credentials are never included in the HTTP requests used for model registry operations.
Root Cause Analysis
Model export uses the internal HttpClient class:
mlflow_export_import/client/http_client.py
This client adds only Bearer tokens to requests:
def _mk_headers(self):
headers = { "User-Agent": USER_AGENT, "Content-Type": "application/json" }
if self.token:
headers["Authorization"] = f"Bearer {self.token}"
return headersHowever:
- Standard MLflow servers typically use BasicAuth
- The client does not look at environment variables:
MLFLOW_TRACKING_USERNAMEMLFLOW_TRACKING_PASSWORD
- Result: model registry API calls (
registered-models/get, etc.) are unauthenticated.
Experiments still work because the high-level MlflowClient handles BasicAuth, but the export tool bypasses it and sends raw HTTP requests.
Reproduction
1. Configure MLflow server with BasicAuth
(e.g., using nginx / ingress auth)
2. Set environment variables:
export MLFLOW_TRACKING_URI=http://127.0.0.1:8080
export MLFLOW_TRACKING_USERNAME=test
export MLFLOW_TRACKING_PASSWORD=test12343. Run model export:
python mlflow_export.py --export-full-model Demo_IrisModel4. Result:
401 Unauthorized
GET /api/2.0/mlflow/registered-models/get?name=Demo_IrisModel
Expected Behavior
The export tool should authenticate using BasicAuth when username and password are set in the environment.
Actual Behavior
HttpClient never attaches BasicAuth headers, only Bearer tokens, causing 401 errors for:
- Registered model lookup
- Model version listing
- Model metadata retrieval
Proposed Fix
Modify _mk_headers() in http_client.py to add BasicAuth support:
def _mk_headers(self):
headers = {
"User-Agent": USER_AGENT,
"Content-Type": "application/json",
}
# 1. Databricks token
if self.token:
headers["Authorization"] = f"Bearer {self.token}"
return headers
# 2. BasicAuth for standard MLflow servers
username = os.getenv("MLFLOW_TRACKING_USERNAME")
password = os.getenv("MLFLOW_TRACKING_PASSWORD")
if username and password:
import base64
raw = f"{username}:{password}"
encoded = base64.b64encode(raw.encode()).decode("utf-8")
headers["Authorization"] = f"Basic {encoded}"
return headersWhy this works
- MLflow already supports BasicAuth for normal usage
- Model export bypasses MLflow client β must send auth headers manually
- This patch restores proper authentication for all registry API calls
Additional Notes
- This bug affects all model export flows, including incremental or full exports.
- Experiments may export correctly, making the issue misleading.
- Fix is backward compatible and does not affect Databricks use cases.
Request
Please review and merge the proposed fix.
If preferred, I can open a pull request with the patch included.
Thanks for maintaining this highly valuable tool! π