Skip to content

[P1] Uncaught errors are diagnostics rather than terminal failures #10

Closed

Description

@ymote

Reproduced during the 2026-09-04 language review at a20753c6cff96ee86758744e227a04460234a832. Priority: P1.

use mod.std
std.assert(false)
42

The optimized runtime reports completed=true, returns 42, and includes an assertion diagnostic. An unknown variable or calling nil followed by 42 behaves similarly. Errors inside a returned array can also leave the outer evaluation marked successful even though JSON conversion subsequently rejects the embedded error value.

This is consequential at an effect boundary:

use mod.std
use mod.tool
std.assert(false)
tool.call("text.echo", "called after failed assertion")

With the CLI's explicit --allow-echo grant, the tool audit records Allowed and the CLI exits zero. A separate two-step workflow reproduced the larger consequence: step guard contains std.assert(false); 42; step effect calls its separately granted echo tool. The CLI reports both steps succeeded, the workflow completed, and an allowed tool event. Thus this is not just misleading result formatting: the next step's authority becomes active after a failed guard.

In vm.rs, handle_errors unwinds to a try when one exists, but otherwise only drains diagnostics. Evaluation::succeeded checks the final value alone. The workflow relies on that predicate before handling output and advancing; see splash-workflow.

Terminate the current evaluation at the first uncaught runtime error. Represent completion, suspension, and failure explicitly. Changing only succeeded() to inspect diagnostics is insufficient: an effect may already have executed by the time that predicate is checked. Preserve the existing distinction between recoverable try/catch errors and uncatchable resource stops. Regression tests should assert that no later effect occurs, no later step activates, and a caught error can still recover deliberately.

Acceptance: implement the described correction, publish the resulting language contract, and add focused regression coverage including applicable capability, streaming-parser, and resource-limit cases.

Fix and executable regressions: PR #19. Workspace tests, explicit vendor suites, formatting, strict Clippy, and the Linux ARM64/RISC-V and Windows GNU compile checks pass locally. All GitHub Actions checks pass on f1e775f, including Linux tests, fuzzing, AddressSanitizer, and Miri. This issue remains open until the fix is merged.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions