<@ULVA73B9P> am getting the following error after ...
# marvin-ai
r
@Marvin am getting the following error after running the prefect flow. context: I want to run the prefect flow locally. error:
Copy code
ValueError: 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.
m
thought for 159.1 seconds
Thanks for the details. That error means something in your run is trying to talk to the Prefect API, but there isn’t an API URL configured. If you want to run “just locally” (no server/Cloud), your flow is fine as long as you don’t call API-dependent features. If you do want orchestration (UI, scheduling, deployments), you need to point Prefect at a running API (local server or Cloud). Next steps to diagnose 1) Confirm what you’re running - Are you executing a script directly (e.g.,
python 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:
Copy code
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:
Copy code
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:
Copy code
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:
Copy code
prefect config unset PREFECT_API_URL
B) Local orchestration (run a local Prefect server + UI) - Start a local server (available in Prefect 3.x):
Copy code
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:
Copy code
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.
r
@Marvin 1. I am directly running the flow which internally has multiple tasks and also calls external API My code doesn't has anything like this:
from prefect.client import get_client
/
await get_client()...
-
from prefect.deployments import run_deployment
2. prefect config view
Copy code
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 API
m
thought for 325.5 seconds
Thanks — the key clue is your active profile and those two settings: - PREFECT_PROFILE='ephemeral' - PREFECT_SERVER_ALLOW_EPHEMERAL_MODE=false - PREFECT_SERVER_EPHEMERAL_ENABLED=false With ephemeral mode disabled, Prefect is not allowed to spin up a local (ephemeral) API if any feature tries to use it. Even if you don’t call the client directly, some built-ins (logging-to-API, events, artifacts, results persistence, etc.) can trigger an API client. Since ephemeral mode is disabled and no PREFECT_API_URL is set, you get the “No Prefect API URL provided” error. Next steps to diagnose 1) Confirm what’s triggering API usage - Re-run with a full stack trace and share the top frames if possible. - Optionally increase verbosity:
Copy code
export 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
Copy code
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:
Copy code
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:
Copy code
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:
Copy code
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.
r
@Marvin Tired option 3 got the below errors:
Copy code
ERROR   | 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 }
m
thought for 163.1 seconds
Thanks — this helps pinpoint what’s happening. What your logs show - uvicorn errors like “[Errno 98] address already in use” on 8010/8575/8815 indicate small webservers are being started multiple times and colliding on ports. - With Dask, multiple worker processes can attempt to start Prefect’s “runner webserver” (used for local orchestration/duplex comms). If that webserver is enabled, each worker may try to bind the same port, causing collisions and “Server process did not start”. Why this happened with Option 3 (local server) - You successfully pointed Prefect to a local API, but the per-runner webserver still tried to start (multiple times under Dask). Those uvicorns are not your main Prefect server (4200); they’re ephemeral runner webservers on various 8xxx ports. Immediate fixes A) Disable the runner webserver entirely (recommended under Dask for local dev) - This prevents those uvicorn processes from starting on each worker.
Copy code
prefect config set PREFECT_RUNNER_SERVER_ENABLE=false
prefect config view
- Keep your local server running and API URL set:
Copy code
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:
Copy code
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
Copy code
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.