<@ULVA73B9P> I started facing an issue with my pre...
# ask-marvin
j
@Marvin I started facing an issue with my prefect, I am not seeing task level logs or graphs
m
thought for 181.2 seconds
Happy to help dig in. A few things can cause task-level logs and the graph to disappear. Let’s quickly narrow it down. First, a few questions: - Which Prefect version are you running (2.x or 3.x)? If unsure, run:
Copy code
prefect version
- Prefect Cloud or self-hosted server? - Did this start after an upgrade or code change? - Do you see flow logs but no task logs, or are all logs missing? - In your flow code, are you calling tasks with
my_task()
(or
.submit()
), or using
my_task.fn()
? Quick checks you can do now - In the UI (Flow Run page → Graph tab), ensure the filters for “Tasks” are enabled. Sometimes the Graph filter hides tasks. - Verify the client-side logging settings being used at runtime:
Copy code
prefect config view --show-sources --show-defaults
Confirm: -
PREFECT_LOGGING_TO_API_ENABLED
is True (otherwise logs won’t reach the UI) - If you rely on
print
, either set
@task(log_prints=True)
or set
PREFECT_LOGGING_LOG_PRINTS=True
- Ensure your code is creating task runs: - Calling
my_task.fn(...)
bypasses orchestration and will not create task runs/logs or appear on the graph. Use
my_task(...)
or
my_task.submit(...)
inside a
@flow
. Self-hosted server checks (Prefect 3.x) - Make sure the task run recorder service is enabled on your API: -
PREFECT_SERVER_SERVICES_TASK_RUN_RECORDER_ENABLED=true
- If this is disabled, task runs/logs/graph data won’t be persisted. - If your flows have very large numbers of tasks, the server may cap what’s returned for the Graph: -
PREFECT_SERVER_FLOW_RUN_GRAPH_MAX_NODES
and
PREFECT_SERVER_FLOW_RUN_GRAPH_MAX_ARTIFACTS
control limits (defaults are high, e.g., 10,000) Minimal code sanity check Try running this to confirm tasks are being recorded/logged:
Copy code
from prefect import flow, task, get_run_logger

@task(log_prints=True, task_run_name="demo-task")
def t(x):
    print(f"print from task: {x}")
    logger = get_run_logger()
    <http://logger.info|logger.info>(f"log from task: {x}")
    return x * 2

@flow(log_prints=True)
def f():
    a = t(1)            # creates a task run
    b = t.submit(2)     # also creates a task run
    # c = t.fn(3)       # would NOT create a task run (bypasses orchestration)
    return a, b.result()

if __name__ == "__main__":
    f()
After running, open the flow run in the UI and check: - Graph tab shows two task nodes - Task-level logs appear under each task run Common causes we see - Using
task.fn(...)
instead of `task(...)`/`.submit(...)` (no task runs/logs/graph) -
PREFECT_LOGGING_TO_API_ENABLED
is False in the runtime environment (no logs in UI) - Relying on
print
without
log_prints=True
(prints won’t appear as logs) - Self-hosted API with task run recorder service disabled - UI Graph filters hiding tasks Docs and references - Tasks concept: Prefect 3.x Tasks - Settings reference: Prefect 3.x Settings - Logging customization: Logging customization If you can share: - Prefect version - Cloud vs self-hosted - A short snippet of how you call your tasks - Output of
prefect config view --show-sources --show-defaults
for the logging-related keys …I can pinpoint the cause quickly and suggest the exact fix.
j
@Marvin I am self-hosting server and worker on aks both have different prefect versions
m
thought for 292.6 seconds
Thanks — version skew between the API (server) and the runtime (worker/flow pods) is the most common cause of “no task logs / no task graph” in self‑hosted 3.x. Why this breaks in 3.x - Task runs and the Graph in 3.x are built from events the client sends to the API. If the API can’t parse those events (older server) or the event recorder service is off, you won’t see task runs, task logs, or the graph. - Major versions must match (2.x vs 3.x will not work). Even within 3.x, running a newer client against an older server can degrade features like task events/graph. Let’s verify and fix 1) Confirm exact versions on both sides - Server/API (from inside the API pod):
Copy code
prefect version
curl -sSL $PREFECT_API_URL/admin/version
prefect config view --show-sources --show-defaults
- Worker runtime (the pod that runs your flow):
Copy code
prefect version
prefect config view --show-sources --show-defaults
Please share the two Prefect versions (e.g., 3.4.2 on server, 3.6.0 on worker), and whether any are on 2.x. 2) Align versions - Pin server and worker images to the same Prefect 3.x minor/patch (e.g., 3.6.0 on both). Avoid floating tags like 3-latest in production. - In Kubernetes manifests/Helm, set the same image tag (e.g., prefecthq/prefect:3.6.0) for both the server API and for the worker/flow job image. 3) Check required services and connectivity on the server - Ensure the task run recorder is enabled on the API: -
PREFECT_SERVER_SERVICES_TASK_RUN_RECORDER_ENABLED=true
- Verify the API can accept WebSocket connections from your workers (load balancer/proxy must allow WS). Blocked WS = no task events created. - For very large flows, verify graph limits aren’t filtering nodes: -
PREFECT_SERVER_FLOW_RUN_GRAPH_MAX_NODES
(default is large, 10,000) 4) Check logging settings on the worker/runtime - Confirm the worker/flow pods are actually sending logs to the API: -
PREFECT_LOGGING_TO_API_ENABLED=true
(default is true) - If you rely on print(), enable: - Per task or flow:
@task(log_prints=True)
/
@flow(log_prints=True)
- Or global:
PREFECT_LOGGING_LOG_PRINTS=true
5) Quick sanity test Run a tiny flow to verify task runs and task logs appear:
Copy code
from prefect import flow, task, get_run_logger

@task(log_prints=True, task_run_name="demo-task")
def t(x):
    print(f"print from task: {x}")
    get_run_logger().info(f"log from task: {x}")
    return x * 2

@flow(log_prints=True)
def f():
    a = t(1)            # creates a task run
    b = t.submit(2)     # creates a task run
    # t.fn(3) would bypass orchestration (no task run/logs/graph)
    return a, b.result()

if __name__ == "__main__":
    f()
Open the flow run in the UI → Graph tab. You should see two task nodes and their logs. If it’s still blank after aligning versions: - Check API pod logs for TaskRunRecorder messages or WS errors. - Check the flow pod logs for version check warnings or WS failures. - Verify UI filters in the Graph tab aren’t hiding tasks. References - Tasks concept: Prefect 3.x Tasks - Settings reference (logging, services, graph limits): Prefect 3.x Settings - Logging customization: Logging customization If you can share: - The exact Prefect versions on server and worker - Whether any side is on 2.x - Output of
prefect config view --show-sources --show-defaults
for logging/service keys …I can give you the precise steps to align and restore task logs/graph.
j
@Marvin My prefect server is 3.6.20 and worker is 3.4.4, how to ensure both are same
m
thought for 158.9 seconds
Got it. Best path is to upgrade your AKS worker and its flow-run job image(s) to match the server at 3.6.20. Here’s how to align everything: 1) Update the worker Deployment image (the poller) - Change the container image for your Kubernetes worker Deployment to Prefect 3.6.20:
Copy code
kubectl -n <namespace> set image deploy/<worker-deployment-name> <container-name>=prefecthq/prefect:3.6.20
kubectl -n <namespace> rollout status deploy/<worker-deployment-name>
kubectl -n <namespace> exec deploy/<worker-deployment-name> -- prefect version
Tip: If you use a custom image, ensure it installs
prefect==3.6.20
. 2) Ensure flow-run jobs also use Prefect 3.6.20 The Kubernetes worker launches a new pod per flow run. That pod image must have the same Prefect version. There are two common ways this is set: - Via the work pool base job template (most common) - Export the default template, edit, and update:
Copy code
prefect work-pool get-default-base-job-template --type kubernetes --file k8s.json
  # edit k8s.json → set "image": "prefecthq/prefect:3.6.20"
  prefect work-pool update "<your-pool-name>" --base-job-template k8s.json
- Via your deployment’s infrastructure overrides (if you set a custom image per deployment) - Update the image there to
prefecthq/prefect:3.6.20
or your custom image that has
prefect==3.6.20
. - If you build your own image, pin Prefect inside it:
Copy code
FROM python:3.11-slim
  RUN pip install --no-cache-dir 'prefect==3.6.20'
  # plus any extras you need, e.g., 'prefect[kubernetes]'
3) Verify versions at runtime - Worker pod:
Copy code
kubectl -n <namespace> exec deploy/<worker-deployment-name> -- prefect version
- Flow-run pod (after triggering a run), check logs for Prefect version or run a quick diagnostic:
Copy code
from prefect import flow, task, get_run_logger, __version__ as PREFECT_VERSION

@task
def show():
    get_run_logger().info(f"Prefect version in task: {PREFECT_VERSION}")

@flow
def f():
    show()

if __name__ == "__main__":
    f()
4) After aligning, if task logs/graph are still missing, double-check: - Server setting:
PREFECT_SERVER_SERVICES_TASK_RUN_RECORDER_ENABLED=true
- Worker logs show no WebSocket/connectivity errors to the API - Logging to API is on in flow pods:
PREFECT_LOGGING_TO_API_ENABLED=true
- If you rely on prints, enable
log_prints=True
on flows/tasks or set
PREFECT_LOGGING_LOG_PRINTS=true
If you want, share: - The worker Deployment name/namespace and whether you use a custom image - Whether your flow-run image is set via the work pool base job template or per-deployment I can give you an exact patch command or template diff.