Skip to content

Errors raised in a bridge carry no source position, so a failing script cannot name its line #15

Closed

Description

@odrobnik

Following #13 — the XCUI-shaped surface is now driving real apps, and the one thing a failing script cannot tell its caller is where it failed.

Interpreter.renderRuntimeError does exactly the right thing when the error carries a position:

4 | let x = undefinedThing + 1
  |         `- error: cannot find 'undefinedThing' in scope

But RuntimeError.offset is non-nil only for .unsupported and .unknownIdentifier. An error raised inside a bridge — which is every real failure in a host that bridges an API — is a .invalid(String) with no position, so it renders as a bare message:

error: no element matches buttons["definitely-not-here"]

An agent holding a forty-line flow with a dozen tap() calls then has to infer the line from the order of its own prints.

Why the host cannot fix it

The host knows what went wrong; only the interpreter knows where it was. By the time the error reaches eval's caller, the expression it came from is gone. Nothing outside the interpreter can attach the position.

Suggested shape

The bridge-invocation boundary already exists — #13 added handling there to make these errors catchable. The same place knows the syntax node it is evaluating, so it could attach its offset on the way out:

// where a bridge closure is invoked
catch let error as RuntimeError {
    throw error.positioned(at: node.positionAfterSkippingLeadingTrivia.utf8Offset)
}

which needs .invalid to be able to carry an offset:

case invalid(String, at: Int? = nil)

Adding the associated value with a default keeps existing .invalid("…") call sites source-compatible, and offset then returns it.

Worth considering the same for a host error that is not a RuntimeError at all: those surface through the catchable-error path from #13, and they have the same problem.

Not blocking

Failures are correct and the script stops at the right point; the message simply lacks a location. But "which line" is the first question anyone asks of a failing script, and the renderer that would answer it already exists — it is only ever handed errors that cannot use it.

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