# How to create more helpful errors in nested interfaces

**URL:** <https://discourse.julialang.org/t/how-to-create-more-helpful-errors-in-nested-interfaces/28380>\
**Category:** General Usage\
**Created:** [September 4, 2019, 5:34pm UTC](https://discourse.julialang.org/t/how-to-create-more-helpful-errors-in-nested-interfaces/28380 "2019-09-04T17:34:29Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![zsunberg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zsunberg/32/1883_2.png) [@zsunberg](https://discourse.julialang.org/u/zsunberg)\
**Post date:** [September 4, 2019, 5:34pm UTC](https://discourse.julialang.org/t/how-to-create-more-helpful-errors-in-nested-interfaces/28380/1 "2019-09-04T17:34:29Z")

</div>

Hi all, I am trying to throw more helpful errors in [POMDPs.jl](https://github.com/JuliaPOMDP/POMDPs.jl). [This package has two nested interfaces](https://juliapomdp.github.io/POMDPs.jl/latest/concepts/). The _explicit interface_ deals with explicit probability distributions; the _generative interface_ samples from distributions that are never explicitly defined. If the explicit interface is implemented for a problem, functions from the generative interface will call explicit functions and sample from the distributions using `rand`.

The problem is that when parts of the interface are not implemented correctly, the `MethodErrors` are very misleading. Users often think they need to implement the explicit interface, which is very difficult or impossible for many problems. The main issue is here: [Helpful error messages for v0.8 · Issue #260 · JuliaPOMDP/POMDPs.jl · GitHub](https://github.com/JuliaPOMDP/POMDPs.jl/issues/260)

## Cartoon version

Below is a cartoon version of the problem. `gen` is a simplified version of the generative interface, and `transition` is a function from the explicit interface - it should return a distribution.

```julia-auto
module POMDPs
    export POMDP, gen, transition, solve

    abstract type POMDP end

    function transition end

    gen(m, s, a) = rand(transition(m, s, a))

    function solve(m::POMDP)
        # in reality this does something much more complex, but uses gen
        sp = gen(m, 1, 1)
        policy = nothing
        return policy
    end
end

using Main.POMDPs

struct MyPOMDP <: POMDP end

solve(MyPOMDP()) # this throws a MethodError for transition - very confusing!!

```

## Desired behavior

- If `transition` is called from `gen` and `transition` is not implemented, an error saying roughly “no state transition model was specified, you can implement it with `gen(MyPOMDP, s, a)` or `transition(MyPOMDP, s, a)`” should be thrown.
- If `transition` is called outside of `gen`, a `MethodError` should be thrown for `transition`
- There can be no overhead when `transition` is implemented - these functions run in inner loops

## Current best idea

My current best idea is to provide a default implementation for `transition` that analyzes the stack trace to see if it was called from within `gen` and then throws an error based on that.

This does not seem like a very good approach - does anyone have a better idea?

---

<div class="post-metadata">

**Author:** ![00vareladavid](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/00vareladavid/32/23521_2.png) [@00vareladavid](https://discourse.julialang.org/u/00vareladavid)\
**Post date:** [September 4, 2019, 6:56pm UTC](https://discourse.julialang.org/t/how-to-create-more-helpful-errors-in-nested-interfaces/28380/2 "2019-09-04T18:56:11Z")

</div>

How about defining a fallback for `transition`:

```julia
function transition(x::T,s,a) where {T<:POMDP}
    error("No state transition model was specified")
end

```

---

<div class="post-metadata">

**Author:** ![zsunberg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zsunberg/32/1883_2.png) [@zsunberg](https://discourse.julialang.org/u/zsunberg)\
**Post date:** [September 4, 2019, 7:43pm UTC](https://discourse.julialang.org/t/how-to-create-more-helpful-errors-in-nested-interfaces/28380/3 "2019-09-04T19:43:07Z")

</div>

In that case, many users will mistakenly think they need to implement `transition` when they actually only need to implement `gen`.

(btw, the default `MethodError` is better than that anyways because it helpfully shows the closest matches)

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [September 5, 2019, 7:36am UTC](https://discourse.julialang.org/t/how-to-create-more-helpful-errors-in-nested-interfaces/28380/4 "2019-09-05T07:36:17Z")

</div>

What about

```julia
function gen(m, s, a)
    if !applicable(transition, m, s, a)
        error("no state transition model was specified, you can implement
               it with gen(MyPOMDP, s, a) or transition(MyPOMDP, s, a)")
    else
        transition(m, s, a)
    end
end

```

Ideally the compiler will optimize away the branch, so this has no cost.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [September 5, 2019, 8:18am UTC](https://discourse.julialang.org/t/how-to-create-more-helpful-errors-in-nested-interfaces/28380/5 "2019-09-05T08:18:13Z")

</div>

> [@Tamas\_Papp](#):
>
> Ideally the compiler will optimize away the branch, so this has no cost.

Ideality and reality are often two different things though.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [September 5, 2019, 8:28am UTC](https://discourse.julialang.org/t/how-to-create-more-helpful-errors-in-nested-interfaces/28380/6 "2019-09-05T08:28:30Z")

</div>

You are right — this is not yet optimized away in the cases I checked.

---

<div class="post-metadata">

**Author:** ![zsunberg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zsunberg/32/1883_2.png) [@zsunberg](https://discourse.julialang.org/u/zsunberg)\
**Post date:** [September 5, 2019, 4:06pm UTC](https://discourse.julialang.org/t/how-to-create-more-helpful-errors-in-nested-interfaces/28380/7 "2019-09-05T16:06:35Z")

</div>

Yeah @Tamas_Papp’s solution is what I’d like to do, and indeed what we have been doing by cheating and observing the method table in @generated functions, but I want to come clean and not cheat anymore!
