Error Handling

kontinue provides structured errors with rich context for debugging and programmatic handling. All SDK functions return errors of type *kontinue.Error which include an error kind, retryability information, and the underlying cause.

Controlling Retry Behavior

When an error occurs in your function, you control whether it triggers a retry. Use these helpers to explicitly mark errors as retryable or non-retryable:

// Non-retryable: fail immediately without retry
return kontinue.NewNonRetryableError(err, "invalid input from external API")

// Retryable: trigger retry if retries are available
return kontinue.NewRetryableError(err, "temporary network failure")

// You can also pass nil for cause
return kontinue.NewNonRetryableError(nil, "validation failed")

Check if an error is retryable:

if kontinue.IsRetryableError(err) {
    // Safe to retry this operation
}

For non-SDK errors (e.g., standard Go errors), retryability defaults to true.

Error Kinds

Each error has a Kind that categorizes it for programmatic handling:

KindDescriptionRetryable
ErrKindInfrastructureKubernetes API or infrastructure errorsYes
ErrKindValidationInvalid options or state provided by userNo
ErrKindChildFailedChild execution failedNo
ErrKindChildCanceledChild execution was canceledNo
ErrKindTimeoutOperation timed outNo
ErrKindInternalInternal SDK errorNo
ErrKindExecutionUser-controlled execution errorUser-defined

Get the error kind:

kind := kontinue.GetErrorKind(err)
switch kind {
case kontinue.ErrKindInfrastructure:
    // Handle infrastructure failure
case kontinue.ErrKindChildFailed:
    // Handle child failure
}

Sentinel Errors

Use errors.Is to check for common error conditions:

if errors.Is(err, kontinue.ErrChildFailed) {
    // A child execution failed
}

if errors.Is(err, kontinue.ErrChildCanceled) {
    // A child execution was canceled
}

if errors.Is(err, kontinue.ErrDuplicateStep) {
    // Step name was reused in the execution
}

if errors.Is(err, kontinue.ErrJobFailed) {
    // A job failed
}

Full Error Details

Use type assertion for complete error details:

var kerr *kontinue.Error
if errors.As(err, &kerr) {
    fmt.Printf("Error: %s\n", kerr.Message)
    if kerr.Child != "" {
        fmt.Printf("Child resource: %s\n", kerr.Child)
    }
}

Example: Handling Child Execution Errors

A common pattern when executing child workflows:

result, err := kontinue.Execute[MyResult](ktx, "child-function", args, &kontinue.ExecuteOptions{})
if err != nil {
    if errors.Is(err, kontinue.ErrChildFailed) {
        // Child failed - handle gracefully
        log.Printf("Child execution failed: %v", err)
        return handleChildFailure(err)
    }
    if kontinue.IsRetryableError(err) {
        // Infrastructure issue - will be retried
        return err
    }
    // Non-retryable error - fail the execution
    return err
}

See Also