Loading relationship in read action is giving error when using actor

So, I have this action in my resource:

  read :get_any do
      get? true

      argument :id, :uuid, allow_nil?: false

      filter expr(id == ^arg(:id))

      prepare build(load: :disposition_agent)
    end

And here is the relationship:

  belongs_to :disposition_agent, User do
      allow_nil? true
      attribute_writable? true
      public? true
    end

If I try to query it without an actor, it works fine:

Core.Marketplace.Markets.Property.get_any!(%{id: "0191e21c-130f-7c45-aa9c-461774866df9"})

But when I try to run it with some actor, I get this error:

iex(21)> Core.Marketplace.Markets.Property.get_any!(%{id: "0191e21c-130f-7c45-aa9c-461774866df9"}, actor: actor)
[debug] QUERY OK source="properties" db=0.5ms idle=1175.9ms
SELECT p0."id", p0."metadata", p0."comment", p0."acquisition_price", p0."county", p0."country", p0."ap_link", p0."due_diligence_date", p0."processing_status", p0."external_id", p0."external_id_type", p0."view_count", p0."over_under_paid", p0."adj_mao", p0."opened_at", p0."normalized_full_address", p0."normalized_county", p0."normalized_state", (p0."house_number"::text::varchar || ($1::varchar::varchar || (p0."street"::text::varchar || ($2::varchar::varchar || (p0."city"::text::varchar || ($3::varchar::varchar || (p0."state"::text::varchar || ($4::varchar::varchar || p0."zip"::text::varchar)::varchar)::varchar)::varchar)::varchar)::varchar)::varchar)::varchar)::text::text FROM "properties" AS p0 WHERE (p0."id"::uuid = $5::uuid) [" ", " - ", ", ", " - ", "0191e21c-130f-7c45-aa9c-461774866df9"]
** (Ash.Error.Invalid) Invalid Error

* Invalid filter value `id in [#Ash.NotLoaded<:attribute, field: :disposition_agent_id>]`: No matching types. Possible types: [[:any, {:array, :same}]]
    at disposition_agent, filter
  (elixir 1.17.2) lib/process.ex:864: Process.info/2
  (ash 3.4.8) lib/ash/error/query/invalid_filter_value.ex:5: Ash.Error.Query.InvalidFilterValue.exception/1
  (ash 3.4.8) lib/ash/query/operator/operator.ex:184: Ash.Query.Operator.try_cast_with_ref/3
  (ash 3.4.8) lib/ash/filter/filter.ex:3086: Ash.Filter.resolve_call/2
  (ash 3.4.8) lib/ash/filter/filter.ex:2522: Ash.Filter.add_expression_part/3
  (ash 3.4.8) lib/ash/filter/filter.ex:2460: anonymous fn/3 in Ash.Filter.parse_expression/2
  (elixir 1.17.2) lib/enum.ex:4858: Enumerable.List.reduce/3
  (elixir 1.17.2) lib/enum.ex:2585: Enum.reduce_while/3
  (ash 3.4.8) lib/ash/filter/filter.ex:334: Ash.Filter.parse/3
  (ash 3.4.8) lib/ash/query/query.ex:2699: Ash.Query.do_filter/3
  (ash 3.4.8) lib/ash/actions/read/relationships.ex:577: anonymous fn/3 in Ash.Actions.Read.Relationships.do_fetch_related_records/4
  (ash 3.4.8) lib/ash/actions/read/relationships.ex:65: Ash.Actions.Read.Relationships.fetch_related_records/3
  (ash 3.4.8) lib/ash/actions/read/relationships.ex:24: Ash.Actions.Read.Relationships.load/3
  (ash 3.4.8) lib/ash/actions/read/read.ex:293: Ash.Actions.Read.do_run/3
  (ash 3.4.8) lib/ash/actions/read/read.ex:81: anonymous fn/3 in Ash.Actions.Read.run/3
  (ash 3.4.8) lib/ash/actions/read/read.ex:80: Ash.Actions.Read.run/3
  (ash 3.4.8) lib/ash.ex:2107: Ash.do_read_one/3
  (ash 3.4.8) lib/ash.ex:2055: Ash.read_one/2
  (ash 3.4.8) lib/ash.ex:2022: Ash.read_one!/2
  (core 1.91.3) deps/ash/lib/ash/code_interface.ex:622: Core.Marketplace.Markets.Property.get_any!/2
  (elixir 1.17.2) src/elixir.erl:386: :elixir.eval_external_handler/3
  (stdlib 6.0.1) erl_eval.erl:904: :erl_eval.do_apply/7
  (elixir 1.17.2) src/elixir.erl:364: :elixir.eval_forms/4
  (elixir 1.17.2) lib/module/parallel_checker.ex:112: Module.ParallelChecker.verify/1
  (iex 1.17.2) lib/iex/evaluator.ex:332: IEx.Evaluator.eval_and_inspect/3
  (iex 1.17.2) lib/iex/evaluator.ex:306: IEx.Evaluator.eval_and_inspect_parsed/3
  (iex 1.17.2) lib/iex/evaluator.ex:295: IEx.Evaluator.parse_eval_inspect/4
  (iex 1.17.2) lib/iex/evaluator.ex:187: IEx.Evaluator.loop/1
  (iex 1.17.2) lib/iex/evaluator.ex:32: IEx.Evaluator.init/5
  (stdlib 6.0.1) proc_lib.erl:329: :proc_lib.init_p_do_apply/3
    (elixir 1.17.2) lib/process.ex:864: Process.info/2
    (ash 3.4.8) lib/ash/error/invalid.ex:3: Ash.Error.Invalid.exception/1
    (ash 3.4.8) /var/home/sezdocs/projects/rebuilt/platform/core/deps/splode/lib/splode.ex:211: Ash.Error.to_class/2
    (ash 3.4.8) lib/ash/error/error.ex:66: Ash.Error.to_error_class/2
    (ash 3.4.8) lib/ash/actions/read/read.ex:29: Ash.Actions.Read.run/3
    (ash 3.4.8) lib/ash/actions/read/relationships.ex:582: anonymous fn/3 in Ash.Actions.Read.Relationships.do_fetch_related_records/4
    (ash 3.4.8) lib/ash/actions/read/relationships.ex:65: Ash.Actions.Read.Relationships.fetch_related_records/3
    (ash 3.4.8) lib/ash/actions/read/relationships.ex:24: Ash.Actions.Read.Relationships.load/3
    (ash 3.4.8) lib/ash/actions/read/read.ex:293: Ash.Actions.Read.do_run/3
    (ash 3.4.8) lib/ash/actions/read/read.ex:81: anonymous fn/3 in Ash.Actions.Read.run/3
    (ash 3.4.8) lib/ash/actions/read/read.ex:80: Ash.Actions.Read.run/3
    (ash 3.4.8) lib/ash.ex:2107: Ash.do_read_one/3
    (ash 3.4.8) lib/ash.ex:2055: Ash.read_one/2
    (ash 3.4.8) lib/ash.ex:2022: Ash.read_one!/2
    (core 1.91.3) deps/ash/lib/ash/code_interface.ex:622: Core.Marketplace.Markets.Property.get_any!/2
    iex:21: (file)

If I remove the prepare build(load: :disposition_agent) from the action and do it outside, it works fine too.

Core.Marketplace.Markets.Property.get_any!(%{id: "0191e21c-130f-7c45-aa9c-461774866df9"}, actor: actor) |> Ash.load!(:disposition_agent)

Any idea what is happening here? That action was working fine on Ash2

Seems like this error comes from ash rbac, removing it solved the issue

:thinking: It looks like the issue is that disposition_agent_id is not being selected on your actor record. In the past, that used to mean that it was just nil, but now (for safety) it is %Ash.NotLoaded{}. My suspicion is that this just caught a bug in your system and potentially policies. Make sure that, when fetching the actor, you are selecting/loading that field.

Not sure what you mean by not being selected in my actor, that field comes from the record I’m fetching, not the actor.

Also, I can reproduce the same error after removing ash rbac and doing these policies:

  field_policies do
    field_policy :* do
      forbid_if always()
    end
  end

  policies do
    policy action(:get_any) do
      authorize_if always()
    end
  end

This will return the exact same error with the disposition_agent_id, shouldn’t it just return the record with all fields as forbidden except the id?

ohh, interesting. I think this is an actual bug which is that we can’t deselect source fields that are required for loading relationships due to policies. Can you open an issue for this on ash?

There you go Ash can’t deselect source fields that are required for loading relationships due to policies · Issue #1457 · ash-project/ash · GitHub