GenServer start_link when stopped in init no longer returns a value in OTP 26?

I need advice as to whether this is a bug in OTP 26 (and where to report it?), or an expected change (is it listed in Otp 26.0 - Erlang/OTP ?)

I have a GenServer that can be stopped in its init callback like this:

defmodule StoppingServer do
  use GenServer

  @spec start_link(keyword()) :: {:ok, pid()} | {:error, atom()}
  def start_link(init_arg) do
    GenServer.start_link(__MODULE__, init_arg)
  end

  def init(_) do
    {:stop, :you_cant_start_me}
  end
end

When I call StoppingServer.start_link([]) with Elixir 1.15 or 1.14 and OTP 25, the call returns a value and then the process exits:

iex()> StoppingServer.start_link([])
{:error, :you_cant_start_me}
** (EXIT from #PID<0.108.0>) shell process exited with reason: :you_cant_start_me

However, when I use OTP 26, the process first exits. If I want to get the return value, I need to trap exits.

iex()> StoppingServer.start_link([])
** (EXIT from #PID<0.113.0>) shell process exited with reason: :you_cant_start_me

Interactive Elixir (1.15.0) - press Ctrl+C to exit (type h() ENTER for help)
iex()> Process.flag(:trap_exit, true)
false
iex()> StoppingServer.start_link([])
{:error, :you_cant_start_me}

Is that expected now? Does the Elixir documentation about GenServer need to be updated? The wording there suggests to me that the value will be returned first:

Returning {:stop, reason} will cause start_link/3 to return {:error, reason} and the process to exit with reason reason without entering the loop or calling terminate/2.

1 Like

Seems like it was an intentional change in OTP 26.

3 Likes