lud

lud

Should Elixir get a new "bad return" exception?

Hello,

When writing libraries it is often useful to define behaviours for library users to implement.
In general, those behaviour callbacks must return a specific type, like {:reply, term, term} or {:ok, term}.

Callbacks should be properly documented and then user-implemented, so it is generally fine to exit or raise if the return value does not adhere to the spec.

In Erlang, this is done by throwing an error with {:bad_return_value, retval}. For instance:

defmodule GS do
  def init(_), do: :foo
end

GenServer.start_link(GS, [])

In that case the error will be formatted as bad return value: :foo by the Elixir Exception module, but it does not tell what did not behave properly.

This is a general problem not related to processes. In libraries you can find code like this:

case user_mod.some_callback("hello") do
  {:ok, v} -> {:ok, do_stuff(v)}
  {:error, _} = err -> err
  other -> exit({:bad_return_value, other})
end

I use this pattern a lot. But the stacktrace will not contain user_mod.some_callback, which is a problem.

You can find occurences in OTP code where the bad return tuple includes the MFA that misbehaved, and it is formatted as MyApp.Application.start(:normal, []) returned a bad value: :foo though I cannot find where this is formatted (currently testing on OTP 27.3.

Erlang processes have some kind of helpful output:

-module(foo).
-export([init/1]).
init([]) -> foo.

Calling that module:

gen_server:start_link(foo, [], []).

Gives the “initial call” information in the crash report:

=CRASH REPORT==== 19-Nov-2025::09:32:46.515514 ===
  crasher:
    initial call: foo:init/1
    pid: <0.96.0>
    registered_name: []
    exception exit: {bad_return_value,foo}
      in function  gen_server:init_it/6 (gen_server.erl, line 2222)

This is for processes but I’m not sure anything standard exists for generic functional code.

How do you handle this case in your libraries or behaviours that you expect your coworkers to implement correctly?

Do you think that a ReturnError exception could be helpful ? (not fan of the name but if follows the pattern of ArgumentError).

So we could use it like that:

case user_mod.some_callback("hello") do
  {:ok, v} -> {:ok, do_stuff(v)}
  {:error, _} = err -> err
  other -> raise ReturnError, module: user_mod, function: :some_callback, value: other
end

And/Or what do you think of a special case in the exception module that would treat {:bad_return_value, {{m,f,a}, term} when is_atom(m) and is_atom(f) and is_list(a) in a special way? (Not sure if backwards compatible though).

Thank you :slight_smile:

Where Next?

Popular in Discussions Top

bartblast
This thread is dedicated to announcing updates to the Hologram documentation, as well as discussing any ideas for improvements and sugges...
New
josefrichter
Has anyone tried Github Speckit or similar projects like AgentOS, BMAD, etc.? They basically offer a bit more structure in context windo...
New
marciol
Thinking about how Contexts on Phoenix 1.3 are beautiful in the simplicity, elegance and minimalism, coalesced in the smallest unity of E...
New
rump13
Hi everyone, I’ve been following Elixir since around 2016 and tinkering with it on and off, but I haven’t had the opportunity to use it ...
New
szsoppa
Hey folks! For the third year in a row, we’re running the Elixir Survey by Curiosum! It’s been live since yesterday, and 300+ people hav...
New
stevensonmt
Has anyone else ever wanted to merge two maps, but have the resulting map only include keys common to both maps? I think of it as analogo...
New
bartblast
Some great comments in the home page thread shifted toward what you’d like to see in Hologram’s future, particularly standalone mode. I’v...
New
derpycoder
So, anyone got a chance to look at this?!? I’m kind of glad this came along. We can just throw this into our Auth pages and won’t have t...
New
New
tristan
First announced on the Erlang Forum, BEAMup is a tool for installing a managing the active instance of BEAM languages. It has support for...
New

Other popular topics Top

TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
273 38985 115
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New

We're in Beta

About us Mission Statement