hashicorp/nomad · error
error executing protected function %w
Error message
error executing protected function %w
What it means
This error is sent through the leaser's error channel when one of the protected functions passed to LockLeaser.Start returns an error. The library aborts the remaining protected functions, cancels the function context, and Start surfaces the wrapped error. It is not a lock/HTTP error — it means your own callback failed while holding the lock.
Source
Thrown at api/locks.go:321
if !errors.Is(err, ErrLockConflict) {
errChannel <- err
}
}
if lockID != "" {
ll.locked = true
funcCtx, funcCancel := context.WithCancel(ctx)
defer funcCancel()
// Execute the lock protected function.
go func() {
defer funcCancel()
for _, f := range protectedFuncs {
err := f(funcCtx)
if err != nil {
errChannel <- fmt.Errorf("error executing protected function %w", err)
return
}
cancel()
}
}()
// Maintain lease is a blocking function, it will return if there is
// an error maintaining the lease or the protected function returned.
err = ll.maintainLease(funcCtx)
if err != nil && !errors.Is(err, ErrLockConflict) {
errChannel <- fmt.Errorf("error renewing the lease: %w", err)
}
}
waitTicker.Stop()
waitTicker = time.NewTicker(ll.waitPeriod)
select {
case <-ctx.Done():View on GitHub (pinned to 482b49bf1a)
Solutions
- Fix the underlying error inside the protected function — inspect the wrapped cause with errors.Is/As on the error returned by Start (it is prefixed 'error executing protected function').
- If the error is benign (e.g. context canceled during shutdown), swallow or filter it inside the protected function and return nil instead.
- Log and return an error only for real failures; treat context.Canceled/DeadlineExceeded separately from operational errors.
- If remaining protected functions must always run, do not return early on failure — collect and log per-function errors.
- Retry the Start call with backoff if the failing protected work is transient (e.g. network to a backing service).
Example fix
// before
func(ctx context.Context) error {
return db.Ping(ctx) // aborts all protected funcs on failure
}
// after
func(ctx context.Context) error {
if err := db.Ping(ctx); err != nil {
if ctx.Err() != nil {
return nil // shutting down; don't abort the leaser
}
return err
}
return nil
} Defensive patterns
Strategy: try-catch
Validate before calling
// validate dependencies the protected function needs BEFORE starting the leaser
if err := db.Ping(context.Background()); err != nil {
return fmt.Errorf("precheck failed, not starting leaser: %w", err)
} Type guard
func IsProtectedFuncError(err error) bool {
return err != nil && strings.Contains(err.Error(), "error executing protected function")
} Try / catch
err := leaser.Start(ctx, work)
if err != nil {
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
// shutdown, not a real failure
return nil
}
return fmt.Errorf("protected work failed: %w", err)
} Prevention
- Make protected functions return nil for benign cancellations (ctx.Err during shutdown)
- Fix or retry failures inside the protected function instead of propagating them when non-fatal
- Keep protected functions idempotent so the whole Start can be retried after failure
- Log the wrapped cause (everything after 'error executing protected function') to find the real failure
- Pre-validate external dependencies (DB, queue) before entering the lock-protected section
When it happens
Trigger: Any protectedFunc passed to LockLeaser.Start(ctx, f1, f2, ...) returning a non-nil error; f1 succeeds but a later fN fails, cancelling the funcCtx mid-run; the protected function returns an error because its own context was cancelled by an outer shutdown that it treats as fatal.
Common situations: Application logic inside the critical section hitting a database/connection error; a protected function returning ctx.Err() (context.Canceled) after the parent context is cancelled during shutdown; misconfigured dependencies used inside the protected function; the function attempting work that is no longer valid once the lease is lost.
Related errors
- lock release: %w
- %w: %w
- invalid websocket connection in context
- invalid digest format
- unsupported checksum format
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/f062c6148a372bd7.
Report an issue: GitHub.