Debugging locally
The easiest way to debug a PyFlink job is to run it locally, where Flink starts an embedded mini-cluster in the same process.Running with Python directly
Debugging UDF logic in isolation
Before running your UDF inside Flink, test it as a plain Python function:Using a debugger with PYFLINK_GATEWAY_DISABLED
The environment variablePYFLINK_GATEWAY_DISABLED prevents PyFlink from starting the JVM gateway. This is useful when you want to step through code that imports pyflink modules without launching a full Flink environment:
Attaching a debugger to the Python UDF worker
To step through UDF code while it runs inside Flink, usedebugpy (the VS Code debug adapter):
Logging
Logging from Python UDFs
Use the standardlogging module inside UDFs. The output goes to the task manager’s log file.
Configuring log level
Set the log level inlog4j2.properties (for Java-side logs) and via the Python logging module (for Python-side logs):
Viewing task manager logs
On a running cluster, access logs through the Flink Web UI:- Open the Flink Web UI (default:
http://localhost:8081). - Click Task Managers in the left sidebar.
- Select a task manager and click the Logs tab.
Profiling
Enabling cProfile
Flink can profile Python UDF workers using Python’s built-incProfile module. Enable it with:
Reading profile output
Flame graphs
For a visual view, convert the profile to a flame graph usingflameprof:
Common errors and solutions
ModuleNotFoundError inside a UDF
ModuleNotFoundError inside a UDF
Symptom: Your UDF raises
ModuleNotFoundError on the cluster even though the library is installed locally.Cause: The Python environment on the task managers does not have the package installed.Solution: Use set_python_requirements() or add_python_archive() to ship the dependency:java.lang.RuntimeException: Python process exited unexpectedly
java.lang.RuntimeException: Python process exited unexpectedly
Symptom: The job fails with a Java exception stating the Python process exited.Cause: An unhandled exception in Python caused the worker to crash, or the Python process ran out of memory.Solution:
- Check the task manager logs for the Python traceback that preceded the Java exception.
- Add try/except in your UDF to catch and log exceptions rather than letting them propagate as crashes.
- Increase the Python worker memory if the crash is OOM-related.
Py4JError or JVM gateway not starting
Py4JError or JVM gateway not starting
Symptom:
py4j.protocol.Py4JError or errors about the JVM gateway failing to start.Cause: Java is not installed, JAVA_HOME is not set, or the Java version is incompatible.Solution:Serialization errors with custom types
Serialization errors with custom types
Symptom:
TypeError or PicklingError when passing custom Python objects between operators.Cause: PyFlink uses CloudPickle to serialize Python objects. Some objects (e.g., lambda captures with unserializable state, database connections) cannot be pickled.Solution: Restructure your UDF to avoid storing unserializable objects. Open connections in open() rather than __init__():Job hangs or produces no output
Job hangs or produces no output
Symptom: The job runs indefinitely without producing results.Cause: Watermarks are not advancing, or
.wait() was not called in a mini-cluster execution.Solution:- For bounded sources, confirm the source has a defined end of input.
- For streaming jobs with event-time windows, make sure your source emits watermarks.
- When running in mini-cluster mode with the Table API, call
.wait()afterexecute_insert():
ClassNotFoundException for connector or format
ClassNotFoundException for connector or format
Symptom: Or add it to Flink’s
java.lang.ClassNotFoundException mentioning a Kafka, JDBC, or other connector class.Cause: The connector JAR is not on the classpath.Solution: Add the JAR to the job:lib/ directory before starting the cluster.Environment variables reference
| Variable | Effect |
|---|---|
PYFLINK_GATEWAY_DISABLED | Prevent PyFlink from starting the JVM gateway. Useful for testing Python-only code paths. |
PYFLINK_GATEWAY_PORT | Connect to an already-running gateway on this port instead of launching a new one. |
FLINK_HOME | Path to the Flink installation directory. PyFlink uses this to find JARs and configuration files. |
JAVA_HOME | Path to the JDK installation. Required if java is not on PATH. |
FLINK_CONF_DIR | Override the directory containing config.yaml. |

