Rupesh Raut
09/10/2025, 1:07 PMValueError: No Prefect API URL provided. Please set PREFECT_API_URL to the address of a running Prefect server.
Provide next steps to diagnose the root cause and then provide the solution for this.Marvin
09/10/2025, 1:07 PMMarvin
09/10/2025, 1:09 PMpython flow.py
), or using prefect deploy
, run_deployment
, flow.from_source(...).deploy(...)
, or flow.serve()
?
- Check your code for API-dependent calls like:
- from prefect.client import get_client
/ await get_client()...
- from prefect.deployments import run_deployment
- Any KV store, events, or flow-run queries via the client
2) Inspect your current Prefect config/profile
- See if PREFECT_API_URL
is set anywhere and what profile you’re using:
prefect config view
- Also check your shell env:
- macOS/Linux: echo $PREFECT_API_URL
- Windows PowerShell: echo $Env:PREFECT_API_URL
3) Decide your intent
- Pure local run (no server): you must avoid any client/API calls in your flow run.
- Local orchestration (UI, deployments, scheduling): start a local server and point your profile at it.
Solutions
A) Pure local execution (no server, no API)
- Run your flow directly as a Python script and remove/guard any API-dependent calls:
from prefect import flow, task
@task
def say_hi():
print("hi")
@flow
def my_flow():
say_hi()
if __name__ == "__main__":
my_flow()
- If your code sometimes uses the API and you want to skip that locally, guard those sections:
from prefect.settings import get_current_settings, PREFECT_API_URL
settings = get_current_settings()
if settings.get(PREFECT_API_URL):
# safe to use client-dependent features
...
else:
# running offline: skip API calls
...
- If you previously set an API URL and want to clear it for local runs:
prefect config unset PREFECT_API_URL
B) Local orchestration (run a local Prefect server + UI)
- Start a local server (available in Prefect 3.x):
prefect server start
- The server runs locally, and the API is typically at http://127.0.0.1:4200/api (UI at http://127.0.0.1:4200).
- Point Prefect to that API in your active profile:
prefect config set PREFECT_API_URL=<http://127.0.0.1:4200/api>
prefect config view
- Re-run your flow. Any deployment- or client-based operations will now be able to connect.
Helpful docs
- Server CLI (start/stop/configure a local server): Prefect 3.x Server CLI
- Settings reference (PREFECT_API_URL, profiles, etc.): Prefect 3.x Settings
Quick check: How are you starting the flow (e.g., python flow.py
, prefect deploy
, flow.serve()
), and do you have any get_client()
or run_deployment
calls in your code? If you share that snippet, I can point to the exact place requiring the API and the minimal change for local-only runs.Rupesh Raut
09/10/2025, 1:19 PMfrom prefect.client import get_client
/ await get_client()...
- from prefect.deployments import run_deployment
2. prefect config view
PREFECT_PROFILE='ephemeral'
PREFECT_SERVER_ALLOW_EPHEMERAL_MODE='false' (from profile)
PREFECT_SERVER_EPHEMERAL_ENABLED='false' (from profile
3. Its pure local flow, it doesn't make any prefect APIMarvin
09/10/2025, 1:19 PMMarvin
09/10/2025, 1:25 PMexport PREFECT_LOGGING_LEVEL=DEBUG # PowerShell: $Env:PREFECT_LOGGING_LEVEL="DEBUG"
python your_flow.py
2) Inspect a few API-related settings in your active profile
prefect config view
Look for:
- PREFECT_LOGGING_TO_API_ENABLED
- PREFECT_EVENTS_ENABLED
- PREFECT_ARTIFACTS_ENABLED
- PREFECT_RESULTS_PERSIST_BY_DEFAULT
- PREFECT_API_URL
- PREFECT_SERVER_* (ephemeral/allow_ephemeral)
3) Double-check you’re not calling any orchestration features
- No flow.serve()
, deployments, or other API features.
Solutions
Option A — Pure local/offline (no Prefect API at all)
Create/use a profile that disables API-touching features and ensures no API URL is set:
prefect profile create local-offline
prefect profile use local-offline
prefect config unset PREFECT_API_URL
prefect config set PREFECT_LOGGING_TO_API_ENABLED=false
prefect config set PREFECT_EVENTS_ENABLED=false
prefect config set PREFECT_ARTIFACTS_ENABLED=false
prefect config set PREFECT_RESULTS_PERSIST_BY_DEFAULT=false
prefect config view
python your_flow.py
This keeps everything in-process and avoids any attempt to contact an API.
Option B — Allow Prefect to use a local ephemeral API if needed (still local)
If you’re okay with Prefect spinning up a lightweight local API only when needed:
prefect config set PREFECT_SERVER_ALLOW_EPHEMERAL_MODE=true
prefect config set PREFECT_SERVER_EPHEMERAL_ENABLED=true
prefect config unset PREFECT_API_URL
python your_flow.py
This is still local; it just lets Prefect satisfy API features automatically.
Option C — Run a local server explicitly
If you prefer a full local server + UI:
prefect server start
prefect config set PREFECT_API_URL=<http://127.0.0.1:4200/api>
prefect config view
python your_flow.py
Helpful docs
- Server CLI: Prefect 3.x Server CLI
- Settings reference: Prefect 3.x Settings
If the error persists after Option A, please share the full stack trace — the first few lines will show exactly which subsystem is trying to create the API client, and I’ll point you to the minimal setting to flip.Rupesh Raut
09/10/2025, 2:04 PMERROR | distributed.worker - Compute Failed
Key: pre_transform-fa3604bd9cd6852a04db3dd68abad10f
State: executing
Exception: "AssertionError('Server process did not start')"
uvicorn.error - [Errno 98] error while attempting to bind on address ('127.0.0.1', 8575): address already in use
14:00:08.298 | INFO | prefect.task_runner.dask - Connecting to an existing Dask cluster at <tcp://127.0.0.1:46495>
14:00:08.306 | INFO | prefect.task_runner.dask - Connecting to an existing Dask cluster at <tcp://127.0.0.1:46495>
14:00:08.313 | ERROR | uvicorn.error - [Errno 98] error while attempting to bind on address ('127.0.0.1', 8575): address already in use
14:00:08.317 | INFO | prefect.task_runner.dask - Connecting to an existing Dask cluster at <tcp://127.0.0.1:46495>
14:00:08.331 | INFO | distributed.scheduler - Receive client connection: PrefectDaskClient-75b575af-8e4e-11f0-8603-bc2411c4d2a4
14:00:08.333 | INFO | distributed.core - Starting established connection to <tcp://127.0.0.1:33172>
14:00:08.333 | INFO | distributed.scheduler - Receive client connection: PrefectDaskClient-75b5c90b-8e4e-11f0-8603-bc2411c4d2a4
14:00:08.334 | INFO | distributed.core - Starting established connection to <tcp://127.0.0.1:33182>
14:00:08.336 | INFO | prefect.task_runner.dask - Connecting to an existing Dask cluster at <tcp://127.0.0.1:46495>
14:00:08.340 | ERROR | uvicorn.error - [Errno 98] error while attempting to bind on address ('127.0.0.1', 8815): address already in use
uvicorn.error - [Errno 98] error while attempting to bind on address ('127.0.0.1', 8010): address already in use
14:00:12.844 | ERROR | Task run 'transform_reducer-641' - Finished in state NotReady("Upstream task run 'None' did not reach a 'COMPLETED' state.", type=PENDING)
Please wait for all submitted tasks to complete before exiting your flow by calling `.wait()` on the `PrefectFuture` returned from your `.submit()` calls.
Also it tried to spin up alot of temporary servers even though
cluster_kwargs={
"n_workers": 4
}Marvin
09/10/2025, 2:04 PMMarvin
09/10/2025, 2:07 PMprefect config set PREFECT_RUNNER_SERVER_ENABLE=false
prefect config view
- Keep your local server running and API URL set:
prefect server start
prefect config set PREFECT_API_URL=<http://127.0.0.1:4200/api>
- Re-run your flow.
B) Clean up port conflicts from stale processes
- If you’ve had prior runs crash, ports may still be bound by orphaned processes.
- macOS/Linux:
- Find: lsof -i :8575
(repeat for 8010/8815/etc)
- Kill: kill -9 <pid>
- Windows (PowerShell):
- Find: netstat -ano | findstr :8575
- Kill: taskkill /PID <pid> /F
C) Quick isolation test (optional)
- Switch to a non-Dask runner briefly to confirm the issue is in the Dask+runner-webserver combo:
from prefect.task_runners import ConcurrentTaskRunner
# in your flow def
@flow(task_runner=ConcurrentTaskRunner())
def my_flow():
...
If this runs cleanly with the local server, the port issues were from the Dask workers starting runner webservers.
Notes on “many temporary servers” with n_workers=4
- Each worker process can attempt to start its own runner webserver if enabled. Disabling it with PREFECT_RUNNER_SERVER_ENABLE=false
stops that behavior.
Double-check your profile after these changes
prefect config view
Key settings that should help here:
- PREFECT_API_URL=http://127.0.0.1:4200/api
- PREFECT_RUNNER_SERVER_ENABLE=false
Docs
- Server CLI (local server): Prefect 3.x Server CLI
- Settings reference: Prefect 3.x Settings
If this doesn’t resolve it, please share:
- Your Prefect version (prefect version
), OS, and Python version
- Your flow/task runner setup snippet (how you instantiate the DaskTaskRunner/cluster)
- A short stack trace around “AssertionError('Server process did not start')”
I’ll map that to the exact setting or runner config to adjust.