Skip to main content

How to Start, Name and End an MLflow Run

· 7 min read
Jagdish Kumawat
Founder @ Dewiride

A run is one execution of your code that MLflow records: its settings, results and files. Everything you log goes into the active run, so how you start and end runs decides where your data lands. This guide starts runs four ways, names them, checks their status, and shows what MLflow does when your code fails halfway, with real output from MLflow 3.18.0.

Syntax​

Syntax
import mlflow

with mlflow.start_run(run_name="<name>") as run:
... # log parameters, metrics and files here

run = mlflow.start_run(run_name="<name>")
... # log here
mlflow.end_run()
PartWhat it means
mlflow.start_run()Starts a run and makes it active: everything you log goes into it
run_name="<name>"The name shown in the UI. Without it, "a random name will be generated"
with ... as run:Ends the run when the block ends: FINISHED if the code succeeded, FAILED if it raised an error
mlflow.end_run()Ends the active run by hand, as FINISHED unless you pass another status
run_id="<run ID>"Opens an existing run again, to log more into it
nested=TrueStarts a run inside the active one

Prerequisites​

The Script​

runs_demo.py starts four runs, each a different way. Build it up piece by piece.

Connect and pick the experiment:

runs_demo.py
import mlflow

mlflow.set_tracking_uri("http://127.0.0.1:8080")
mlflow.set_experiment("runs-demo")

1. A named run in a with block, the usual way:

runs_demo.py (add at the end)
with mlflow.start_run(run_name="first-named-run") as run:
print("Inside the block:", run.info.run_name, mlflow.active_run().info.status)
print("After the block:", mlflow.get_run(run.info.run_id).info.status)

mlflow.start_run() starts a run and makes it active; mlflow.active_run() returns it. When the block ends, MLflow ends the run.

2. A run without a name:

runs_demo.py (add at the end)
with mlflow.start_run() as run:
print("No name given, MLflow picked:", run.info.run_name)

3. A run started and ended by hand, for code that can't use a with block:

runs_demo.py (add at the end)
run = mlflow.start_run(run_name="manual-start-and-end")
mlflow.log_param("style", "manual")
mlflow.end_run()
print("Manual run:", mlflow.get_run(run.info.run_id).info.status)

4. A run where the code fails:

runs_demo.py (add at the end)
try:
with mlflow.start_run(run_name="run-that-fails") as run:
raise ValueError("training stopped early")
except ValueError as error:
print("Caught:", error)
print("Failed run:", mlflow.get_run(run.info.run_id).info.status)
print("Active run now:", mlflow.active_run())

Run It​

Terminal
uv run python runs_demo.py
Output
2026/11/13 17:07:55 INFO mlflow.tracking.fluent: Experiment with name 'runs-demo' does not exist. Creating a new experiment.
Inside the block: first-named-run RUNNING
🏃 View run first-named-run at: http://127.0.0.1:8080/#/experiments/4/runs/b19958e538d34ba5b02bc7a6b8f5a0fc
🧪 View experiment at: http://127.0.0.1:8080/#/experiments/4
After the block: FINISHED
No name given, MLflow picked: righteous-steed-81
🏃 View run righteous-steed-81 at: http://127.0.0.1:8080/#/experiments/4/runs/c71dd749aeee41989e255d8dae763328
🧪 View experiment at: http://127.0.0.1:8080/#/experiments/4
🏃 View run manual-start-and-end at: http://127.0.0.1:8080/#/experiments/4/runs/f86b2686272e4a749cce9afb7761dab7
🧪 View experiment at: http://127.0.0.1:8080/#/experiments/4
Manual run: FINISHED
🏃 View run run-that-fails at: http://127.0.0.1:8080/#/experiments/4/runs/29fe9bf6d3ff48e6ac4f1f5535cb2393
🧪 View experiment at: http://127.0.0.1:8080/#/experiments/4
Caught: training stopped early
Failed run: FAILED
Active run now: None

What the Output Shows​

  • Status changes from RUNNING to FINISHED. Inside the block the run is running; when the block ends, MLflow marks it finished.
  • No name? MLflow makes one up: righteous-steed-81, an adjective, an animal and a number.
  • end_run() finishes a run you started by hand. Forget it, and the run stays active until your program exits.
  • An error inside the block marks the run FAILED. The with block ended the run with that status before the error reached the except. That's the main reason to prefer with: a crash never leaves a run looking healthy.
  • MLflow prints two links when each run ends: the run and its experiment.
  • After all four, no run is active (None).

The Runs page shows the result, newest first, with a red cross for the failed run:

The runs-demo Runs page in MLflow with four runs: run-that-fails with a red failed icon, and manual-start-and-end, righteous-steed-81 and first-named-run with green finished checks, each with its duration and its source script, runs_demo.py, shortened in the table.

Naming Runs Well​

Good run names say what's different about the run, such as 300-trees or 50-trees-depth-8. A command-line option is an easy way to pass one in: MLflow Tutorial for Machine Learning in Python — Part 1 adds --run-name to its training command. The run's ID is what identifies it for MLflow; names don't have to be unique.

Common Mistakes​

MistakeWhat happensDo this instead
mlflow.start_run() without end_run()The run stays active, and later logging goes into itUse a with block, or call end_run()
Catching errors inside the with blockMLflow never sees the error, so a broken run shows FinishedLet errors leave the block, or mark the run yourself with mlflow.end_run(status="FAILED")
Using run names as IDsNames repeat across runsUse run.info.run_id

Troubleshooting​

SymptomLikely causeFix
A run is stuck as Running in the UIThe program stopped before the run was endedUse with blocks; end leftover runs with MlflowClient().set_terminated(run_id)
Runs land in the wrong experimentNo set_experiment() before start_run()Call set_experiment() first

FAQ​

Can I start a run inside another run?​

Yes, with mlflow.start_run(nested=True). Nested runs group related runs, such as each try in a hyperparameter search, under one parent; a later part of the MLflow series uses them.

How do I find a run later?​

By its ID in the UI's URL, by name in the runs table's search box, or with mlflow.search_runs().

What statuses can a run have?​

RUNNING, FINISHED, FAILED, KILLED and SCHEDULED. Your code mostly sees the first three.

Conclusion​

mlflow.start_run(run_name=...) in a with block started a RUNNING run and ended it as FINISHED; without a name MLflow called it righteous-steed-81; start_run() with end_run() did the same by hand; and an exception inside the block ended the run as FAILED, shown with a red cross in the UI.

Additional Resources​