Ecto has_many empty relation is causing an error when retrieving the record

I have a schema (“customers”) with a has_many association (“subscriptions”), and my issue is that when the “customers” record is created, the has_many “subscriptions” association will always be an empty enum. This is fine when inserting, but results in a ** (UndefinedFunctionError) function Mongo.Ecto.in_transaction?/1 is undefined or private error when retrieving the record from the DB.

Any ideas how to resolve this?

Customers Schema

  schema "customers" do
    field :name, :string
    field :phone, :string
    field :email, :string

    field :stripe_id, :string
    field :description, :string

    field :balance, :float
    field :currency, :string
    field :discount, :float
    field :payment_method, :string

    field :deleted_from_stripe, :boolean

    has_one :address, Address
    has_many :subscriptions, Subscription


Customers Changeset

  def changeset(customer, params) do
    |> cast(params, @attrs)
    |> cast_assoc(:address, with: &Address.changeset/2)
    |> cast_assoc(:subscriptions, with: &Subscription.changeset/2)

Customers Query

  def find_customers() do
    query =
      from t in Customer,
      preload: [:address, :subscriptions],
      select: t


Couple things that would be helpful for understanding this:

  • specific version numbers (of Ecto & the Mongo adapter especially)
  • the full stack trace

The following is wildly guessing based on the symptoms.

I’m suspicious of this line - prior to this commit there was an in_transaction? call used while preloading more than one association.

Version Numbers

mongo_ecto: 0.2.0
phoenix_ecto: 3.0.1
ecto: 2.0.6

Stack Trace

13:29:08.495 [error] GenServer #PID<0.629.0> terminating
** (UndefinedFunctionError) function Mongo.Ecto.in_transaction?/1 is undefined or private
    (mongo_ecto 0.2.0) Mongo.Ecto.in_transaction?(MyApp.Repo)
    (ecto 2.0.6) lib/ecto/repo/queryable.ex:133: Ecto.Repo.Queryable.execute/5
    (ecto 2.0.6) lib/ecto/repo/queryable.ex:40: Ecto.Repo.Queryable.all/4
    (myapp 0.0.2) lib/myapp_web/channels/customers_channel.ex:33: MyAppWeb.CustomersChannel.handle_in/3
    (phoenix 1.5.8) lib/phoenix/channel/server.ex:315: Phoenix.Channel.Server.handle_info/2
    (stdlib gen_server.erl:637: :gen_server.try_dispatch/4
    (stdlib gen_server.erl:711: :gen_server.handle_msg/6
    (stdlib proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: %Phoenix.Socket.Message{event: "load_all", join_ref: "12", payload: %{"token" => "SFMyNTY.g2gDYQJuBgA0Y8eFhAFiAAFRgA.W65RbNogwpPasDOHQ7Wjh1yQdQskoSVuZE_e70gMGeQ"}, ref: "13", topic: "all:customers"}

Yup, this line calls the preloader:

Based on the chatter in the elixir_mongo issues, it sounds like support for Ecto 2 wasn’t easy and required some pushback to the core Ecto library, for instance:

That commit didn’t land until Ecto 2.1.0 though.

1 Like

Thanks, I’ve updated my dependencies to use mongodb_ecto which supports Ecto 2.1.0 rather than mongo_ecto.

I’m now receiving the following error when I try to compile my app:

** (CompileError) lib/my_app/accounts/subscriptions/price.ex:3: module Ecto.Model is not loaded and could not be found
    (elixir 1.10.3) expanding macro: Kernel.use/1
    lib/my_app/accounts/subscriptions/price.ex:3: MyApp.Accounts.Subscriptions.Price (module)
    expanding macro: MyApp.Model.__using__/1
    lib/my_app/accounts/subscriptions/price.ex:3: MyApp.Accounts.Subscriptions.Price (module)
    (elixir 1.10.3) expanding macro: Kernel.use/1
    lib/my_app/accounts/subscriptions/price.ex:3: MyApp.Accounts.Subscriptions.Price (module)
    (elixir 1.10.3) lib/kernel/parallel_compiler.ex:304: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7

Can you shed any light on this?

Set Up

Am I missing something here? I’ve been over this with a fine tooth comb and all seems to be correct.


      {:phoenix_ecto, "~> 3.1"},
      {:mongodb_ecto, "~> 0.2"},


  def application do
      mod: {MyApp.Application, []},
      extra_applications: [:logger, :mongodb_ecto, :ecto, :runtime_tools, :edeliver]


defmodule MyApp.Repo do
  use Ecto.Repo,
    otp_app: :my_app,
    adapter: Mongo.Ecto


defmodule MyApp.Model do
  defmacro __using__(_) do
    quote do
      use Ecto.Model
      @primary_key {:id, :binary_id, autogenerate: true}
      @foreign_key_type :binary_id # For associations

And in my models: use MyApp.Model

Ecto.Model was deprecated in 2.0 and removed outright in 2.1

1 Like

Ok thanks for that, I’ve replaced Ecto.Model with Ecto.Schema and compilation is now fine, but the app is now failing to load the front end JS - looks like I’ve started down a rabbit hole :joy:

Indeed :stuck_out_tongue: My only recommendation is to take it slow and not try to upgrade straight from 2.1 to 3.9, even though that’s going to mean making changes that are then undone/further changed later.

Oh I’m not trying to upgrade to 3.9, 2.1 is fine for me, don’t need anything special from Ecto, only basic CRUD operations.

Strange how this has impacted on loading my assets though, the only dependencies I’ve changed are phoenix_ecto (upgraded from 3.0 to 3.1), mongo_ecto (changed to mongodb_ecto) :man_shrugging: