ichiban / prolog

The only reasonable scripting engine for Go.
MIT License
564 stars 27 forks source link

Instability of Error Message Retrieval from Exceptions #311

Closed ccamel closed 7 months ago

ccamel commented 7 months ago

Issue

The process of retrieving the string representation of an Exception - engine.Exception.Error() - is found to be inconsistent across multiple calls. The first call returns the accurate error message, but the second and subsequent calls return the string ....

The following minimal code demonstrates the issue:

package main

import (
    "fmt"
    "github.com/ichiban/prolog"
    "github.com/ichiban/prolog/engine"
)

func Foo(_ *engine.VM, foo engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise {
    return engine.Error(engine.TypeError(engine.NewAtom("foo"), foo, env))
}

func main() {
    i := &prolog.Interpreter{}
    i.Register1(engine.NewAtom("foo"), Foo)

    sol := i.QuerySolution("foo(What).")
    err := sol.Err()
    if err != nil {
        fmt.Printf("Error: %s\n", err.Error()) // πŸ‘‰ Error: error(type_error(foo,_4),foo/1)
        fmt.Printf("Error: %s\n", err.Error()) // πŸ‘‰ Error: ...
    }
}

Analysis

The issue appears to originate from the global variable engine.defaultWriteOptions used for managing the compounds already visited in the string conversion process of the engine.Exception.

In the first call, the table of visited compounds is populated, leading to the accurate error message. However, in subsequent calls, as the compound has already been visited, the writer generates the string ... instead. 😞

Impact

This side effect is particularly unexpected as it's common to get consistent string returns from exceptions.

Additionally, the effect is quite subtle in the context of our unit tests using smartystreets/goconvey, where assertions are structured as follows:

  So(err, ShouldNotBeNil)
  So(err.Error(), ShouldEqual, wanted.err.Error())

In this scenario, the first call (which is introspective) generates an accurate error string. However, on the second call, the output becomes ..., which is unfortunately incorrect. πŸ˜₯

ichiban commented 7 months ago

Could you try v1.1.1 or newer, please? I think it's fixed in https://github.com/ichiban/prolog/pull/298. Let me know if the problem persists!

ccamel commented 7 months ago

@ichiban, yes it's fixed in version v1.1.3. :relieved:

Thanks!