Error: `key :manual not found in: nil` with create_query using graphql

So I got this simple resource:
defmodule Zelo.Planner.PlanResult do
@moduledoc false
use Ash.Resource,
domain: Zelo.Planner,
authorizers: [Ash.Policy.Authorizer],
extensions: [
AshJason.Resource,
AshGraphql.Resource,
AshJsonApi.Resource
]

code_interface do
domain Cvs.Planner
define :create, action: :create
define :run_planner, action: :run_planner
end

actions do
create :create do
primary? true
accept :*

argument :routes, {:array, :map}, allow_nil?: false
change manage_relationship(:routes, type: :direct_control)
end

create :run_planner do
manual Zelo.Planner.ManualPlanCreate
end
end

policies do
policy always() do
authorize_if always()
end
end

graphql do
type :plan_result

mutations do
create :run_planner, :run_planner
end
end

json_api do
type "plan_result"
end

attributes do
uuid_primary_key :id
end

relationships do
has_many :routes, Zelo.Planner.RouteResult do
public? true
end
end
end


defmodule Zelo.Planner.ManualPlanCreate do
@moduledoc false
use Ash.Resource.ManualCreate

alias Ash.Changeset
alias Zelo.Planner.PlanResult

@impl true
def create(changeset, opts, context) do
{:ok,
%PlanResult{
id: "clappen",
routes: [
%{
vehicle_id: "vehicle-123",
distance: 1234,
duration: 1234,
polyline: "SDFGSDG",
projected_departure_time: DateTime.utc_now(),
projected_end_time: DateTime.utc_now()
}
]
}}
end
end
defmodule Zelo.Planner.PlanResult do
@moduledoc false
use Ash.Resource,
domain: Zelo.Planner,
authorizers: [Ash.Policy.Authorizer],
extensions: [
AshJason.Resource,
AshGraphql.Resource,
AshJsonApi.Resource
]

code_interface do
domain Cvs.Planner
define :create, action: :create
define :run_planner, action: :run_planner
end

actions do
create :create do
primary? true
accept :*

argument :routes, {:array, :map}, allow_nil?: false
change manage_relationship(:routes, type: :direct_control)
end

create :run_planner do
manual Zelo.Planner.ManualPlanCreate
end
end

policies do
policy always() do
authorize_if always()
end
end

graphql do
type :plan_result

mutations do
create :run_planner, :run_planner
end
end

json_api do
type "plan_result"
end

attributes do
uuid_primary_key :id
end

relationships do
has_many :routes, Zelo.Planner.RouteResult do
public? true
end
end
end


defmodule Zelo.Planner.ManualPlanCreate do
@moduledoc false
use Ash.Resource.ManualCreate

alias Ash.Changeset
alias Zelo.Planner.PlanResult

@impl true
def create(changeset, opts, context) do
{:ok,
%PlanResult{
id: "clappen",
routes: [
%{
vehicle_id: "vehicle-123",
distance: 1234,
duration: 1234,
polyline: "SDFGSDG",
projected_departure_time: DateTime.utc_now(),
projected_end_time: DateTime.utc_now()
}
]
}}
end
end
And using graphql I query
mutation {
runPlanner {
result {
id
routes {
vehicleId
}
}
}
}
mutation {
runPlanner {
result {
id
routes {
vehicleId
}
}
}
}
And this gives me the following stacktrace:
6 Replies
jeroen11dijk
jeroen11dijkOP•2w ago
(Ash.Error.Unknown) Bread Crumbs:
Exception raised in: Zelo.Planner.PlanResult.run_planner Exception raised in: Zelo.Planner.PlanResult.run_planner
Unknown Error *
(KeyError) key :manual not found in: nil If you are using the dot syntax, such as map.field, make sure the left-hand side of the dot is a map (ash 3.5.10) lib/ash/actions/read/read.ex:437: Ash.Actions.Read.load_relationships/3 (ash 3.5.10) lib/ash/actions/read/read.ex:354: Ash.Actions.Read.do_run/3 (ash 3.5.10) lib/ash/actions/read/read.ex:89: anonymous fn/3 in Ash.Actions.Read.run/3 (ash 3.5.10) lib/ash/actions/read/read.ex:88: Ash.Actions.Read.run/3 (ash 3.5.10) lib/ash.ex:1914: Ash.load/3 (ash 3.5.10) lib/ash.ex:1868: Ash.load/3 (ash 3.5.10) lib/ash/actions/helpers.ex:713: Ash.Actions.Helpers.load/4 (ash 3.5.10) lib/ash/actions/create/create.ex:488: Ash.Actions.Create.commit/3 (ash 3.5.10) lib/ash/actions/create/create.ex:132: Ash.Actions.Create.do_run/4 (ash 3.5.10) lib/ash/actions/create/create.ex:50: Ash.Actions.Create.run/4 (ash_graphql 1.7.10) lib/graphql/resolver.ex:1510: AshGraphql.Graphql.Resolver.mutate/2 (absinthe 1.7.9) lib/absinthe/phase/document/execution/resolution.ex:234: Absinthe.Phase.Document.Execution.Resolution.reduce_resolution/1 (absinthe 1.7.9) lib/absinthe/phase/document/execution/resolution.ex:189: Absinthe.Phase.Document.Execution.Resolution.do_resolve_field/3 (absinthe 1.7.9) lib/absinthe/phase/document/execution/resolution.ex:174: Absinthe.Phase.Document.Execution.Resolution.do_resolve_fields/6 (absinthe 1.7.9) lib/absinthe/phase/document/execution/resolution.ex:145: Absinthe.Phase.Document.Execution.Resolution.resolve_fields/4 (absinthe 1.7.9) lib/absinthe/phase/document/execution/resolution.ex:88: Absinthe.Phase.Document.Execution.Resolution.walk_result/5 (absinthe 1.7.9) lib/absinthe/phase/document/execution/resolution.ex:67: Absinthe.Phase.Document.Execution.Resolution.perform_resolution/3 (absinthe 1.7.9) lib/absinth (ash 3.5.10) lib/ash/actions/read/read.ex:437: Ash.Actions.Read.load_relationships/3 (ash 3.5.10) lib/ash/actions/read/read.ex:354: Ash.Actions.Read.do_run/3 (ash 3.5.10) lib/ash/actions/read/read.ex:89: anonymous fn/3 in Ash.Actions.Read.run/3 (ash 3.5.10) lib/ash/actions/read/read.ex:88: Ash.Actions.Read.run/3 (ash 3.5.10) lib/ash.ex:1914: Ash.load/3 (ash 3.5.10) lib/ash.ex:1868: Ash.load/3 (ash 3.5.10) lib/ash/actions/helpers.ex:713: Ash.Actions.Helpers.load/4 (ash 3.5.10) lib/ash/actions/create/create.ex:488: Ash.Actions.Create.commit/3 (ash 3.5.10) lib/ash/actions/create/create.ex:132: Ash.Actions.Create.do_run/4 (ash 3.5.10) lib/ash/actions/create/create.ex:50: Ash.Actions.Create.run/4 (ash_graphql 1.7.10) lib/graphql/resolver.ex:1510: AshGraphql.Graphql.Resolver.mutate/2 (absinthe 1.7.9) lib/absinthe/phase/document/execution/resolution.ex:234: Absinthe.Phase.Document.Execution.Resolution.reduce_resolution/1 (absinthe 1.7.9) lib/absinthe/phase/document/execution/resolution.ex:189: Absinthe.Phase.Document.Execution.Resolution.do_resolve_field/3 (absinthe 1.7.9) lib/absinthe/phase/document/execution/resolution.ex:174: Absinthe.Phase.Document.Execution.Resolution.do_resolve_fields/6 (absinthe 1.7.9) lib/absinthe/phase/document/execution/resolution.ex:145: Absinthe.Phase.Document.Execution.Resolution.resolve_fields/4 (absinthe 1.7.9) lib/absinthe/phase/document/execution/resolution.ex:88: Absinthe.Phase.Document.Execution.Resolution.walk_result/5 (absinthe 1.7.9) lib/absinthe/phase/document/execution/resolution.ex:67: Absinthe.Phase.Document.Execution.Resolution.perform_resolution/3 (absinthe 1.7.9) lib/absinthe/phase/document/execution/resolution.ex:24: Absinthe.Phase.Document.Execution.Resolution.resolve_current/3 (absinthe 1.7.9) lib/absinthe/pipeline.ex:408: Absinthe.Pipeline.run_phase/3 (absinthe_plug 1.5.9) lib/absinthe/plug.ex:545: Absinthe.Plug.run_query/4 And so far I have been unable to get around this, although using a primary create with manage_relationships seems the way to go I also tried adding the default read but then I get the error that there is no data and that I need to use set_data somewhere but it also seems unclear to me where. Since using it in read seems like it would already be too late
ZachDaniel
ZachDaniel•2w ago
You should make that an embedded attribute instead of a relationship
jeroen11dijk
jeroen11dijkOP•2w ago
Thanks that was exactly it 😃 How do I define the attribute as an array so I can expose it for graphql
attribute {:array, Zelo.Planner.RouteResult} do
allow_nil? false
public? true
end
attribute {:array, Zelo.Planner.RouteResult} do
allow_nil? false
public? true
end
This doesnt work but using map also doesnt sound great
ZachDaniel
ZachDaniel•2w ago
WHen you say "this doesn't work" what do you mean? The resource needs the :embedded data layer
jeroen11dijk
jeroen11dijkOP•2w ago
misread the error, and I got it to work 😅 its really nice way to setup the API though
ZachDaniel
ZachDaniel•2w ago
with embeds you mean?

Did you find this page helpful?