From 550954c7a3b3ee8b8da15eb5ad4547a96e92f2a6 Mon Sep 17 00:00:00 2001 From: Greg Lin Date: Thu, 16 Jul 2026 18:10:01 -0500 Subject: [PATCH] Explain unexpected work recursion before logging fatally The unmarked-recursion message named only the work type, so a process killed by FatalRecurseCheck gave no hint of why it exited or where the recursion came from. State the cause and the fix (mark the context with ContextWithExpectedRecursion) in both log paths, and include the stack in the fatal path to locate the unmarked call chain. --- pkg/rsqueue/queue/work.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/rsqueue/queue/work.go b/pkg/rsqueue/queue/work.go index a207136..49b0ba9 100644 --- a/pkg/rsqueue/queue/work.go +++ b/pkg/rsqueue/queue/work.go @@ -6,6 +6,7 @@ import ( "context" "fmt" "log" + "runtime/debug" "time" ) @@ -86,9 +87,11 @@ func (a *OptionalRecurser) OptionallyRecurse(ctx context.Context, run func()) { // Are we expecting recursion? allowed := ctx.Value(CtxAllowsRecursion) if allowed == nil { - msg := fmt.Sprintf("Work with type %d attempted recursion without being marked for recursion", r.WorkType) + msg := fmt.Sprintf("Work with type %d attempted recursion without being marked for recursion. "+ + "The work's context reached a nested queue operation without ContextWithExpectedRecursion; "+ + "mark the context in the work's runner.", r.WorkType) if a.fatalRecurseCheck { - log.Fatal(msg) + log.Fatalf("%s Exiting because FatalRecurseCheck is enabled. Recursion stack:\n%s", msg, debug.Stack()) } else { log.Println(msg) }