Hi, On Thu, Oct 8, 2026 at 3:54 PM Hayato Kuroda (Fujitsu) <[email protected]> wrote: > > Dear Vignesh, > > > While reviewing another thread at [1], I found an issue where an error > > relayed from a parallel apply worker can get an unrelated CONTEXT line > > from the leader process. > > ProcessParallelApplyMessage() in applyparallelworker.c sets > > error_context_stack to the leader's apply_error_context_stack before > > calling ereport(ERROR). As a result, when errfinish() processes the > > error, the leader's error context callback runs again and adds the > > leader's current replication context. This can be incorrect if the > > leader is processing a different transaction when it receives the > > error from the parallel worker. > > Good catch and agreed your analysis. > > I checked other examples in core, and parallel query seems to handle > correctly. > It has an attribute ParallelContext::error_context_stack which preserves an > error > context at that time, see CreateParallelContext(). When the parallel worker > raises > an ERROR, the leader backend can consume its message and raise it again, and > at > that time the error context is restored from the ParallelContext. > > I think the easiest fix is to use apply_error_context_stack for preserving the > error context before entering the loop, attached patch implements the idea. > IIUC no contexts can be stacked at the begining of the worker, i.e., > apply_error_context_stack can be NULL in any case. So the global variable can > be > removed if we clean up more aggressively. I also felt the name can be changed, > but it's retained for now because the variable has been exposed.
I think it makes sense to preserve the error context before the loop, to be consistent with what parallel query does. But I think we'd better simply save the error context to apply_error_context_stack before adding the error callback as that looks better than indirectly getting the previous one after adding a new one, and it can save readers a few cycles. E.g., +apply_error_context_stack = error_context_stack; errcallback.callback = apply_error_callback; ... Best Regards, Zhijie Hou
