1
votes

New to elixir and I'm following along with José Valim's post https://howistart.org/posts/elixir/1

I am having trouble having the Supervisor to start a child as i get the error:

iex(1)> Portal.shoot(:orange) {:error, {:invalid_child_spec, [:orange]}}

Help would be greatly appreciated!

Here is the Portal module

defmodule Portal do
use Application

def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
        worker(Portal.Door, [])
    ]

    opts = [strategy: :simple_one_for_one, name: Portal.Supervisor]
    Supervisor.start_link(children, opts)
end

@doc """
Shoots a new door with the given `color`
"""
def shoot(color) do
    Supervisor.start_child(Portal.Supervisor, [color])
end

Here is the Portal.Door module and the start_link function that should be getting invoked

defmodule Portal.Door do

def start_link(color) do
    Agent.start_link(fn -> [] end, name: color)
end
2
Your code works for me. Are you sure this is the exact code that shows that error?Dogbert
Yes. It was a straight copy paste from my editor. I do have other functions in the files (also from the tutorial) but they shouldn't have any effect as they are not being invoked. @Dogbert would it be helpful to see the entire .ex filesdhuenecke
Yes. Could you first copy the code in the question, add the 2 missing end, and see if it works? I copied this and added the 2 missing end and it worked for me yesterday.Dogbert

2 Answers

2
votes

I ran into the same issue with that tutorial. The tutorial is correct if you're using a Mix version before 1.4. However, in Mix 1.4+ the supervisor code should be placed in the Portal.Application module in lib/portal/application.ex. Here's the Github pull request for this change with some discussion around the thinking behind the change: https://github.com/elixir-lang/elixir/pull/5275

To fix the issue, you'll need to remove the Application code you added to the Portal module and add it to the Portal.Application module in lib/portal/application.ex. Your Portal.Application module should look like this:

defmodule Portal.Application do
  @moduledoc false

  use Application

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      worker(Portal.Door, [])
    ]

    opts = [strategy: :simple_one_for_one, name: Portal.Supervisor]
    Supervisor.start_link(children, opts)
  end
end
1
votes

Maybe your mix version is 1.4. Mix 1.4 with --sup automatically included start/2 implementation in individual Application module. In your scene, that is in lib/portal/application.ex. You can modify the start function there. The official release notes