An LPC Function Without the atomic Modifier Does Not Roll Back on Caught Error

Claim

In the eOS-Harness MVA running against DGD 1.7.9 plus the eOS-kernellib HTTP/1 platform at upstream c5b1dee, an LPC function declared WITHOUT the atomic modifier that mutates dataspace and then calls error() does NOT roll back its mutations when the error is caught anywhere up the call stack. The empirical evidence covers three dispatch shapes:

In all three cases the boot-log error trace carries the [caught] annotation but does NOT carry the [atomic] annotation that DGD emits when an atomic envelope is engaged. The runtime treats the modifier-less function body as ordinary (non-transactional) execution; statements commit immediately, and the error fires after the commits without a rollback path.

Grounds

This is an Empirical Observation. The grounds are the paired positive Observation's smoke B transcript plus two additional probes (C and D) authored in the same phase. The probes are HTTP-reachable and were exercised against the live runtime 2026-05-17.

Setup (identical to the paired positive Observation):

Probe C transcript (same-object dispatch; caught):

$ curl -s http://127.0.0.1:8080/probe-counter
probe_counter=0
$ curl -s http://127.0.0.1:8080/probe-c
probe_c_caught=1
$ curl -s http://127.0.0.1:8080/probe-counter
probe_counter=1

The same-object wrapper probe_c_same_object_caught calls probe_increment_no_atomic() locally (no -> operator) wrapped in catch. The catch fires (probe_c_caught=1); the error was observed. probe_counter advances from 0 to 1, so the increment is NOT rolled back.

Probe D transcript (cross-object dispatch; NO immediate catch; outer dispatcher catch):

$ curl -sS -X POST http://127.0.0.1:8080/probe-d
500 Internal Server Error
probe: deliberate failure without atomic modifier

$ curl -s http://127.0.0.1:8080/probe-counter
probe_counter=2

The handler dispatches to /usr/Test/atomic_demo->probe_increment_no_atomic() WITHOUT wrapping the call in catch. The error propagates through the handler's handle() (no catch in that path) up to /usr/WWW/obj/server::dispatch at line 143 where err = catch(result = handler->handle(...)) catches it; server.c then emits a 500 response. probe_counter advances from 1 to 2 (the prior probe C run left it at 1), so the increment is NOT rolled back even when the immediate caller does not catch.

Boot-log error traces (key evidence):

** probe: deliberate failure without atomic modifier [caught]
                                /usr/WWW/obj/server#NNN
   429   receiveBytes              /usr/HTTP/lib/Connection1
    99   receiveHeaders            /usr/HTTP/api/lib/Server1
   183   receiveRequest            /usr/WWW/obj/server
   143   dispatch                  /usr/WWW/obj/server
                                /usr/Test/sys/atomic_handler
   140   handle                    /usr/Test/sys/atomic_handler
    99   handleProbeC              /usr/Test/sys/atomic_handler
                                /usr/Test/atomic_demo
    71 * probe_c_same_object_caught   /usr/Test/atomic_demo
    56   probe_increment_no_atomic    /usr/Test/atomic_demo

** probe: deliberate failure without atomic modifier [caught]
                                /usr/WWW/obj/server#NNN
   429   receiveBytes             /usr/HTTP/lib/Connection1
    99   receiveHeaders           /usr/HTTP/api/lib/Server1
   193   receiveRequest           /usr/WWW/obj/server
   143 * dispatch                 /usr/WWW/obj/server
                                /usr/Test/sys/atomic_handler
   143   handle                   /usr/Test/sys/atomic_handler
   116   handleProbeD             /usr/Test/sys/atomic_handler
                                /usr/Test/atomic_demo
    56   probe_increment_no_atomic   /usr/Test/atomic_demo

The * marks the catch frame. Neither trace carries the [atomic] annotation that DGD emits for atomic envelopes (visible in the paired positive Observation's smoke A trace ** deliberate failure for atomicity demonstration [atomic]). The runtime does not engage an atomic envelope at any frame in either probe; the absence of the annotation is the runtime's own evidence that no rollback is in flight when the error propagates.

Mechanism discrimination outcomes:

The paired positive Observation named three candidate mechanisms to explain smoke B's modifier-less persistence:

After the probes, the candidate (b2) -- any catch up the stack absorbs a putative default rollback -- remains formally undistinguished from (a). Constructing a no-catch-anywhere probe is impractical in this MVA: the outer /usr/WWW/obj/server::dispatch always catches errors propagating from application handlers (otherwise a deliberate-error route would crash the per-connection server clone); the operator console's code verb similarly wraps evaluation in a catch. Both (a) and (b2) lead to the same operational conclusion: in any realistic application path with a catch somewhere up the stack, the atomic modifier is required for function-body rollback.

What the evidence establishes:

What the evidence does not establish:

What Would Revise It

Sources

Relations