Skip to main content

Error Hierarchy

Error Hierarchy in flyte-sdk

Understanding Runtime Errors

When tasks execute within flyte-sdk, various issues can arise, from problems in your own code to underlying system failures. To provide a clear and actionable understanding of these issues, flyte-sdk establishes a structured error hierarchy rooted in BaseRuntimeError. This base class and its specialized subclasses categorize runtime exceptions, making it easier to diagnose and address problems.

The Foundation: BaseRuntimeError

All runtime errors in flyte-sdk inherit from errors.BaseRuntimeError. This class extends Python's built-in RuntimeError and introduces specific attributes to enrich error information:

  • code: A string identifier for the specific error.
  • kind: An ErrorKind enum value (e.g., "user", "system", "unknown") that categorizes the error's origin.
  • root_cause_message: A detailed message describing the error.
  • worker: An optional string identifying the worker that encountered the error.

This foundational class ensures that every runtime error carries consistent diagnostic information.

class BaseRuntimeError(RuntimeError):
"""
Base class for all Union runtime errors. These errors are raised when the underlying task execution fails, either
because of a user error, system error or an unknown error.
"""

def __init__(self, code: str, kind: ErrorKind, root_cause_message: str, worker: str | None = None):
super().__init__(root_cause_message)
self.code = code
self.kind = kind
self.worker = worker

Categorizing Failures: RuntimeUserError, RuntimeSystemError, and RuntimeUnknownError

Building upon BaseRuntimeError, flyte-sdk provides three specialized subclasses to precisely categorize the nature of a runtime failure:

RuntimeUserError: When Your Code Encounters an Issue

When a task fails due to an error within the user's provided code, flyte-sdk raises a errors.RuntimeUserError. This clearly signals that the problem lies in the task's implementation rather than the flyte-sdk system itself.

For instance, if a generic Exception occurs during a task's execution, flyte-sdk catches it and re-raises it as a RuntimeUserError. This ensures that all user-originated exceptions are consistently typed and categorized.

class RuntimeUserError(BaseRuntimeError):
"""
This error is raised when the underlying task execution fails because of an error in the user's code.
"""

def __init__(self, code: str, message: str, worker: str | None = None):
super().__init__(code, "user", message, worker)

A common scenario where RuntimeUserError is employed is when wrapping unexpected exceptions within a task's execution logic. In src/flyte/_task.py, flyte-sdk ensures that any unhandled exception from your task code is presented as a RuntimeUserError:

try:
# Some user code that might raise an exception
1 / 0
except Exception as e:
raise RuntimeUserError(type(e).__name__, str(e)) from e

This pattern helps maintain a clear distinction between system-level issues and application-level bugs.

RuntimeSystemError: Indicating Platform-Level Problems

When an issue arises from the flyte-sdk platform itself, or an external dependency it relies on, a errors.RuntimeSystemError is raised. This type of error indicates a problem that is typically outside the scope of the user's application code, such as an uninitialized component, a network issue with a service, or an internal bug within flyte-sdk.

class RuntimeSystemError(BaseRuntimeError):
"""
This error is raised when the underlying task execution fails because of a system error. This could be a bug in the
Union system or a bug in the user's code.
"""

def __init__(self, code: str, message: str, worker: str | None = None):
super().__init__(code, "system", message, worker)

You might encounter RuntimeSystemError in various operational contexts. For example, if the task controller is not properly initialized, flyte-sdk signals this critical setup issue:

controller_initialized = False # Assume controller is not initialized for this example
if controller_initialized:
pass # Controller is initialized, do something
else:
raise RuntimeSystemError("BadContext", "Controller is not initialized.")

Another example is during data transfer operations, where issues with signed URLs or uploads are wrapped as RuntimeSystemError to indicate a platform-level failure:

if e.code() == grpc.StatusCode.NOT_FOUND:
raise RuntimeSystemError(
"NotFound", f"Failed to get signed url for {fp}, please check your project and domain: {e.details()}"
)

Similarly, if an upload to a signed URL fails with an unexpected HTTP status, it's categorized as a system error:

if put_resp.status_code != 200:
raise RuntimeSystemError(
"UploadFailed",
f"Failed to upload {fp} to {resp.signed_url}, status code: {put_resp.status_code}, "
f"response: {put_resp.text}",
)

These examples from src/flyte/remote/_data.py demonstrate how RuntimeSystemError provides consistent error reporting for infrastructure-related problems.

RuntimeUnknownError: When the Origin is Unclear

In situations where the exact cause or origin (user vs. system) of a runtime failure cannot be definitively determined, flyte-sdk raises a errors.RuntimeUnknownError. This serves as a fallback for errors that don't clearly fit into the user or system categories.

class RuntimeUnknownError(BaseRuntimeError):
"""
This error is raised when the underlying task execution fails because of an unknown error.
"""

def __init__(self, code: str, message: str, worker: str | None = None):
super().__init__(code, "unknown", message, worker)

While less common, RuntimeUnknownError ensures that all runtime failures are captured within the flyte-sdk error hierarchy, even when their root cause is ambiguous.

Leveraging the Error Hierarchy for Debugging

The distinct error types (RuntimeUserError, RuntimeSystemError, RuntimeUnknownError) are crucial for effective debugging and error handling. When you encounter an error during task execution, examining the type of BaseRuntimeError subclass immediately tells you where to focus your investigation:

  • RuntimeUserError: Indicates a problem within your task's Python code. Review your logic, inputs, and dependencies.
  • RuntimeSystemError: Suggests an issue with the flyte-sdk environment, configuration, or underlying services. This might require checking flyte-sdk logs, infrastructure status, or contacting support.
  • RuntimeUnknownError: Points to an unexpected failure that requires deeper investigation into both your code and the system context.

By providing this clear categorization, flyte-sdk helps you quickly pinpoint the source of runtime issues, streamlining the debugging process.