Error Handling
Scalar UDFs can also set @geneva.udf(timeout=...) to enforce a per-row timeout in
seconds. Timeout failures surface as ordinary TimeoutError, so existing
on_error, retry, and skip_on_error() behavior applies unchanged.
This timeout support is scalar-only and uses Unix SIGALRM / setitimer
semantics at runtime. It also requires execution on the worker process main
thread. It works inside MultiProcessBatchApplier worker subprocesses because
each child executes batches on its own main thread, but it still uses
process-global signal state. UDFs or libraries that install their own
SIGALRM handlers/timers, or that depend on main-thread signal behavior while
coordinating work in background threads, may be incompatible.
Fatal Worker Errors
Scalar UDF backfill also classifies fatal worker loss into public Geneva exception types:
FatalWorkerTransientErrorFatalWorkerOOMErrorFatalWorkerCrashErrorFatalWorkerExitError
By default, FatalWorkerTransientError is retried up to 3 task-level attempts,
even if the user does not specify an on_error policy.
If the user provides on_error and does not explicitly match
FatalWorkerTransientError, Geneva still applies that default retry behavior.
If the user does explicitly match it, the user configuration wins.
Examples:
from geneva import Retry, Fail, udf
from geneva.errors import FatalWorkerTransientError
@udf(
data_type=pa.int64(),
on_error=[Retry(FatalWorkerTransientError, max_attempts=5)],
)
def retry_infra_failures(x: int) -> int:
return x * 2
@udf(
data_type=pa.int64(),
on_error=[Fail(FatalWorkerTransientError)],
)
def fail_on_infra_failures(x: int) -> int:
return x * 2
Exception Matchers
geneva.debug.error_store.Retry
Bases: ExceptionMatcher
Retry on matching exceptions with backoff
Parameters:
-
*exceptions(type[Exception], default:()) –Exception types to match
-
match(str, default:None) –Regex pattern to match in exception message. Simple strings work as substring matches (e.g., "rate limit"). Use (?i) for case-insensitive matching.
-
max_attempts(int, default:3) –Maximum number of attempts (default: 3)
-
backoff(str, default:'exponential') –Backoff strategy: "exponential" (default), "fixed", or "linear"
Examples:
Retry(ConnectionError, TimeoutError, max_attempts=3)
Retry(ValueError, match="rate limit", max_attempts=5)
Retry(APIError, match=r"429|rate.?limit")
Retry(APIError, match=r"(?i)rate limit") # case-insensitive
geneva.debug.error_store.Skip
Bases: ExceptionMatcher
Skip row (return None) on matching exceptions
Parameters:
-
*exceptions(type[Exception], default:()) –Exception types to match
-
match(str, default:None) –Regex pattern to match in exception message
-
max_skip_count(int, default:None) –Maximum number of rows that can be skipped before failing the job. Only used when passed via
skip_on_error(). -
max_skip_fraction(float, default:None) –Maximum fraction of rows (0.0-1.0) that can be skipped before failing the job. Only used when passed via
skip_on_error().
Examples:
Skip(ValueError, KeyError)
Skip(ValueError, match="invalid input")
geneva.debug.error_store.Fail
Bases: ExceptionMatcher
Fail job immediately on matching exceptions
Parameters:
-
*exceptions(type[Exception], default:()) –Exception types to match
-
match(str, default:None) –Regex pattern to match in exception message
Examples:
Fail(AuthError)
Fail(ValueError, match="fatal")
Helper Functions
geneva.debug.error_store.retry_transient
Retry transient network errors (ConnectionError, TimeoutError, OSError).
Parameters:
-
max_attempts(int, default:3) –Maximum number of attempts (default: 3)
-
backoff(str, default:'exponential') –Backoff strategy: "exponential" (default), "fixed", or "linear"
Returns:
-
list[ExceptionMatcher]–Matcher list for use with on_error parameter
Examples:
@udf(data_type=pa.int32(), on_error=retry_transient())
@udf(data_type=pa.int32(), on_error=retry_transient(max_attempts=5))
geneva.debug.error_store.retry_all
Retry any exception.
Parameters:
-
max_attempts(int, default:3) –Maximum number of attempts (default: 3)
-
backoff(str, default:'exponential') –Backoff strategy: "exponential" (default), "fixed", or "linear"
Returns:
-
list[ExceptionMatcher]–Matcher list for use with on_error parameter
Examples:
@udf(data_type=pa.int32(), on_error=retry_all())
@udf(data_type=pa.int32(), on_error=retry_all(max_attempts=5))
geneva.debug.error_store.skip_on_error
skip_on_error(
max_skip_count: int | None = None,
max_skip_fraction: float | None = None,
) -> list[ExceptionMatcher]
Skip (return None) for any exception.
Parameters:
-
max_skip_count(int, default:None) –Maximum number of rows that can be skipped before the job fails. If both
max_skip_countandmax_skip_fractionare set, whichever threshold is hit first triggers failure. -
max_skip_fraction(float, default:None) –Maximum fraction of rows (0.0-1.0) that can be skipped before the job fails. The fraction is computed as
skipped / total_processed_so_far.
Returns:
-
list[ExceptionMatcher]–Matcher list for use with on_error parameter
Examples:
@udf(data_type=pa.int32(), on_error=skip_on_error())
@udf(data_type=pa.int32(), on_error=skip_on_error(max_skip_count=100))
@udf(data_type=pa.int32(), on_error=skip_on_error(max_skip_fraction=0.05))
@udf(
data_type=pa.int32(),
on_error=skip_on_error(max_skip_count=100, max_skip_fraction=0.05),
)
geneva.debug.error_store.fail_fast
Fail immediately on any exception (default behavior).
Returns:
-
list[ExceptionMatcher]–Empty matcher list (no special handling)
Examples:
@udf(data_type=pa.int32(), on_error=fail_fast())
Configuration
geneva.debug.error_store.ErrorHandlingConfig
Configuration for UDF error handling behavior
geneva.debug.error_store.UDFRetryConfig
Retry configuration for UDF execution using tenacity semantics
retry_transient
retry_transient(max_attempts: int = 3) -> UDFRetryConfig
Retry common transient errors (network, timeouts)
Parameters:
-
max_attempts(int, default:3) –Maximum number of attempts including the initial try
geneva.debug.error_store.ErrorRecord
UDF execution error record, stored in geneva_errors table
timestamp
timestamp: datetime = field(
factory=dt_now_utc,
metadata={"pa_type": timestamp("us", tz="UTC")},
)