AE
Ash Elixirβ€’6d ago
mcoll

Ash.Type.Tuple Enumerable not implemented

I have an attribute of type :tuple defined like this:
attribute :model, :tuple do
constraints [
fields: [
alpha: [type: :float, description: "The alpha parameter for the beta model"],
beta: [type: :float, description: "The beta parameter for the beta model"],
t: [type: :float, description: "The half life of the fact in days"],
]
]
allow_nil? false
default fn -> Katarineko.Srs.default_model(1, nil, nil) end
end
attribute :model, :tuple do
constraints [
fields: [
alpha: [type: :float, description: "The alpha parameter for the beta model"],
beta: [type: :float, description: "The beta parameter for the beta model"],
t: [type: :float, description: "The half life of the fact in days"],
]
]
allow_nil? false
default fn -> Katarineko.Srs.default_model(1, nil, nil) end
end
When I create an instance of this model
fact = Katarineko.Learning.create_fact
fact = Katarineko.Learning.create_fact
I get this error
{:error,
%Ash.Error.Unknown{
bread_crumbs: ["Error returned from: Katarineko.Learning.Fact.create"],
changeset: "#Changeset<>",
errors: [
%Ash.Error.Unknown.UnknownError{
error: "** (Protocol.UndefinedError) protocol Enumerable not implemented for type Tuple\n\nGot value:\n\n {3.0, 3.0, 1.0}\n",
field: nil,
value: nil,
splode: Ash.Error,
bread_crumbs: ["Error returned from: Katarineko.Learning.Fact.create"],
vars: [],
path: [],
stacktrace: #Splode.Stacktrace<>,
class: :unknown
}
]
}}
{:error,
%Ash.Error.Unknown{
bread_crumbs: ["Error returned from: Katarineko.Learning.Fact.create"],
changeset: "#Changeset<>",
errors: [
%Ash.Error.Unknown.UnknownError{
error: "** (Protocol.UndefinedError) protocol Enumerable not implemented for type Tuple\n\nGot value:\n\n {3.0, 3.0, 1.0}\n",
field: nil,
value: nil,
splode: Ash.Error,
bread_crumbs: ["Error returned from: Katarineko.Learning.Fact.create"],
vars: [],
path: [],
stacktrace: #Splode.Stacktrace<>,
class: :unknown
}
]
}}
Is this expected? Am I doing something wrong?
45 Replies
mcoll
mcollOPβ€’6d ago
Okay, managed to get the stacktrace by calling Splode.ErrorClass.error_messages on the UnknownError, and it seems to happen here: https://github.com/ash-project/ash/blob/v3.5.7/lib/ash/type/tuple.ex#L158-L159
GitHub
ash/lib/ash/type/tuple.ex at v3.5.7 Β· ash-project/ash
A declarative, extensible framework for building Elixir applications. - ash-project/ash
mcoll
mcollOPβ€’6d ago
I guess it should use list instead of value there? The one defined at 155? I'm testing the fix and opening a PR okay, so that worked, but then it fails loading the struct from postgres
ZachDaniel
ZachDanielβ€’6d ago
πŸ₯²this is a new type and while I tried it w/ storage in my personal use case I only used it for an argument If you can PR a test showing the issue and the fix you have so far I can review
mcoll
mcollOPβ€’6d ago
I think I have the loading side working, will push a PR soon and we can review if it makes sense!
ZachDaniel
ZachDanielβ€’6d ago
Awesome thank you πŸ™‚ Also pretty sure you already earned a pink name didn't you? I'll grant it now.
mcoll
mcollOPβ€’6d ago
hahaha, thanks, I'm not sure yet
mcoll
mcollOPβ€’6d ago
GitHub
fix: Tuple loader and serializer by MarceColl Β· Pull Request #2049...
The Tuple type had three bugs: In dump_to_native the original tuple value was used instead of the tuple converted to a list. This caused Elixir to complain that Tuple doesn&amp;#39;t have Enumerab...
mcoll
mcollOPβ€’5d ago
@Zach Daniel there are some more problems actually. For some reason this was working before but it's not working now. I have this action
update :review do
change get_and_lock_for_update()

argument :result, :atom do
allow_nil? false
constraints one_of: [:success, :failure]
end

change set_attribute(:last_review, DateTime.utc_now())
change increment(:successes), where: [argument_equals(:result, :success)]
change increment(:total)

change after_action(fn changeset, record, _context ->
record = Ash.load!(record, :days_since_last_review)

{:ok, new_model} = Katarineko.Srs.update_recall(
record.model,
record.successes,
record.total,
record.days_since_last_review,
true,
nil,
nil
)

record
|> Ash.Changeset.for_update(:update)
|> Ash.Changeset.force_change_attribute(:model, new_model)
|> IO.inspect()
|> Ash.update()
end)

require_atomic? false
end
update :review do
change get_and_lock_for_update()

argument :result, :atom do
allow_nil? false
constraints one_of: [:success, :failure]
end

change set_attribute(:last_review, DateTime.utc_now())
change increment(:successes), where: [argument_equals(:result, :success)]
change increment(:total)

change after_action(fn changeset, record, _context ->
record = Ash.load!(record, :days_since_last_review)

{:ok, new_model} = Katarineko.Srs.update_recall(
record.model,
record.successes,
record.total,
record.days_since_last_review,
true,
nil,
nil
)

record
|> Ash.Changeset.for_update(:update)
|> Ash.Changeset.force_change_attribute(:model, new_model)
|> IO.inspect()
|> Ash.update()
end)

require_atomic? false
end
However when I attempt to run it I get
1) test failure review on after-created state (Katarineko.Learning.FactTest)
test/katarineko/learning/fact_test.exs:16
** (Ash.Error.Invalid)
Bread Crumbs:
> Error returned from: Katarineko.Learning.Fact.review

Invalid Error

* Invalid filter value `{3.9731554659619825, 3.973155465962138, 0.7295532145344957}` supplied in `#Ecto.Changeset<action: nil, changes: %{}, errors: [], data: #Katarineko.Learning.Fact<>, valid?: true, ...>`
(elixir 1.18.3) lib/enum.ex:2546: Enum."-reduce/3-lists^foldl/2-0-"/3
(elixir 1.18.3) lib/enum.ex:1840: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
(elixir 1.18.3) lib/enum.ex:2546: Enum."-reduce/3-lists^foldl/2-0-"/3
(ecto 3.12.5) lib/ecto/repo/queryable.ex:216: Ecto.Repo.Queryable.execute/4
(ash_postgres 2.5.19) lib/data_layer.ex:1532: AshPostgres.DataLayer.update_query/4
(ash 3.5.9) lib/ash/actions/update/bulk.ex:570: Ash.Actions.Update.Bulk.do_atomic_update/5
(ash 3.5.9) lib/ash/actions/update/bulk.ex:256: Ash.Actions.Update.Bulk.run/6
(ash 3.5.9) lib/ash/actions/update/update.ex:169: Ash.Actions.Update.run/4
(ash 3.5.9) lib/ash.ex:2740: Ash.update/3
(ash 3.5.9) lib/ash/changeset/changeset.ex:4266: anonymous fn/2 in Ash.Changeset.run_after_actions/3
1) test failure review on after-created state (Katarineko.Learning.FactTest)
test/katarineko/learning/fact_test.exs:16
** (Ash.Error.Invalid)
Bread Crumbs:
> Error returned from: Katarineko.Learning.Fact.review

Invalid Error

* Invalid filter value `{3.9731554659619825, 3.973155465962138, 0.7295532145344957}` supplied in `#Ecto.Changeset<action: nil, changes: %{}, errors: [], data: #Katarineko.Learning.Fact<>, valid?: true, ...>`
(elixir 1.18.3) lib/enum.ex:2546: Enum."-reduce/3-lists^foldl/2-0-"/3
(elixir 1.18.3) lib/enum.ex:1840: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
(elixir 1.18.3) lib/enum.ex:2546: Enum."-reduce/3-lists^foldl/2-0-"/3
(ecto 3.12.5) lib/ecto/repo/queryable.ex:216: Ecto.Repo.Queryable.execute/4
(ash_postgres 2.5.19) lib/data_layer.ex:1532: AshPostgres.DataLayer.update_query/4
(ash 3.5.9) lib/ash/actions/update/bulk.ex:570: Ash.Actions.Update.Bulk.do_atomic_update/5
(ash 3.5.9) lib/ash/actions/update/bulk.ex:256: Ash.Actions.Update.Bulk.run/6
(ash 3.5.9) lib/ash/actions/update/update.ex:169: Ash.Actions.Update.run/4
(ash 3.5.9) lib/ash.ex:2740: Ash.update/3
(ash 3.5.9) lib/ash/changeset/changeset.ex:4266: anonymous fn/2 in Ash.Changeset.run_after_actions/3
I found that internally we were checking if model is the same as the previous one to detect if we need to update the updated_at field, so I decided to set the updated_at myself to see if that solved the issue by adding
|> Ash.Changeset.force_change_attribute(:updated_at, DateTime.utc_now())
|> Ash.Changeset.force_change_attribute(:updated_at, DateTime.utc_now())
And even though the query I see from ecto doesn't have a conditional on model anymore, I still get the error which is a bit confusing
#Ecto.Query<from f0 in Katarineko.Learning.Fact, as: 0,
where: type(
type(as(0).id, {:parameterized, {Ash.Type.Integer.EctoType, []}}),
{:parameterized, {Ash.Type.Integer.EctoType, []}}
) ==
type(
type(^50, {:parameterized, {Ash.Type.Integer.EctoType, []}}),
{:parameterized, {Ash.Type.Integer.EctoType, []}}
),
update: [
set: [
model:
type(
type(
^{3.004335183048418, 3.0043351830485556, 1.0270002134258505},
{:parameterized, {Ash.Type.Tuple.EctoType, fields: []}}
),
{:parameterized,
{Ash.Type.Tuple.EctoType,
fields: [
alpha: [
description: "The alpha parameter for the beta model",
allow_nil?: true,
constraints: [],
type: Ash.Type.Float
],
beta: [
description: "The beta parameter for the beta model",
allow_nil?: true,
constraints: [],
type: Ash.Type.Float
],
t: [
description: "The half life of the fact in days",
allow_nil?: true,
constraints: [],
type: Ash.Type.Float
]
]}}
),
updated_at:
type(
type(
^~U[2025-05-20 08:49:00.853915Z],
{:parameterized, {Ash.Type.UtcDatetimeUsec.EctoType, precision: :microsecond}}
),
{:parameterized,
{Ash.Type.UtcDatetimeUsec.EctoType,
precision: :microsecond, cast_dates_as: :start_of_day, timezone: :utc}}
)
]
],
select: struct(f0, [:id, :total, :inserted_at, :updated_at, :model, :successes, :last_review])>
#Ecto.Query<from f0 in Katarineko.Learning.Fact, as: 0,
where: type(
type(as(0).id, {:parameterized, {Ash.Type.Integer.EctoType, []}}),
{:parameterized, {Ash.Type.Integer.EctoType, []}}
) ==
type(
type(^50, {:parameterized, {Ash.Type.Integer.EctoType, []}}),
{:parameterized, {Ash.Type.Integer.EctoType, []}}
),
update: [
set: [
model:
type(
type(
^{3.004335183048418, 3.0043351830485556, 1.0270002134258505},
{:parameterized, {Ash.Type.Tuple.EctoType, fields: []}}
),
{:parameterized,
{Ash.Type.Tuple.EctoType,
fields: [
alpha: [
description: "The alpha parameter for the beta model",
allow_nil?: true,
constraints: [],
type: Ash.Type.Float
],
beta: [
description: "The beta parameter for the beta model",
allow_nil?: true,
constraints: [],
type: Ash.Type.Float
],
t: [
description: "The half life of the fact in days",
allow_nil?: true,
constraints: [],
type: Ash.Type.Float
]
]}}
),
updated_at:
type(
type(
^~U[2025-05-20 08:49:00.853915Z],
{:parameterized, {Ash.Type.UtcDatetimeUsec.EctoType, precision: :microsecond}}
),
{:parameterized,
{Ash.Type.UtcDatetimeUsec.EctoType,
precision: :microsecond, cast_dates_as: :start_of_day, timezone: :utc}}
)
]
],
select: struct(f0, [:id, :total, :inserted_at, :updated_at, :model, :successes, :last_review])>
This is the query I've seen for this any ideas?
ZachDaniel
ZachDanielβ€’5d ago
Hmm....that would typically happen when it fails to cast to stored for example Are any of the tuple types callbacks returning errors while that happens?
mcoll
mcollOPβ€’5d ago
I tried debugging those by adding some logs in the callbacks for cast_input and cast_stored but none of them returned errors that I could see how do you usually debug this things? I'm not super experienced with elixir and my current testing setup is very rudimentary. I'm modifying things directly inside of deps/ to add IO.inspects here and there, then I mix deps.clean --build ash/ecto and rebuild
ZachDaniel
ZachDanielβ€’5d ago
It depends. In this case it's deep down in the belly of things so it's not the easiest I'd typically have the packages cloned down and use path dependencies So I can more easily work on the dependency code
mcoll
mcollOPβ€’5d ago
makes sense
ZachDaniel
ZachDanielβ€’5d ago
In this case Ecto does some stuff to hide error stack traces IIRC that makes it a bit tough to see what's going on In the next Ecto version that will be configurable and I can likely make this better that way For now I'll probably clone down ash_postgres and inspect where that error is probably coming from etc.
mcoll
mcollOPβ€’5d ago
what I'm confused is that it complains about a filter, but there is no filter above on the given tuple
ZachDaniel
ZachDanielβ€’5d ago
Yeah, that error is "synthesized" Like it's getting a different error and turning it into that because it's usually that
mcoll
mcollOPβ€’5d ago
ah, I see, that's why you say that I need to dig into what Ecto is doing
ZachDaniel
ZachDanielβ€’5d ago
It's complicated πŸ˜‚ maybe you can open a PR w/ a test in ash_postgres? I'm happy to investigate or give pointers If you look in data_layer.ex there is a place where that invalid filter value is created Like the error I mean You could do some debugging there to see the original error
mcoll
mcollOPβ€’5d ago
defp handle_raised_error(%Ecto.Query.CastError{} = e, stacktrace, context, resource) do
handle_raised_error(
Ash.Error.Query.InvalidFilterValue.exception(value: e.value, context: context),
stacktrace,
context,
resource
)
end
defp handle_raised_error(%Ecto.Query.CastError{} = e, stacktrace, context, resource) do
handle_raised_error(
Ash.Error.Query.InvalidFilterValue.exception(value: e.value, context: context),
stacktrace,
context,
resource
)
end
This one?
ZachDaniel
ZachDanielβ€’5d ago
Yep!
mcoll
mcollOPβ€’5d ago
mcoll
mcollOPβ€’5d ago
That's without the forced updated_at, this one is with
value `{3.004335183048418, 3.0043351830485556, 1.0270002134258505}` in `update` cannot be cast to type #Ash.Type.Tuple.EctoType<[fields: []]> in query:

from f0 in Katarineko.Learning.Fact,
as: 0,
where: type(
type(as(0).id, {:parameterized, {Ash.Type.Integer.EctoType, []}}),
{:parameterized, {Ash.Type.Integer.EctoType, []}}
) ==
type(
type(^64, {:parameterized, {Ash.Type.Integer.EctoType, []}}),
{:parameterized, {Ash.Type.Integer.EctoType, []}}
),
update: [
set: [
updated_at:
type(
type(
^~U[2025-05-20 11:02:30.068792Z],
{:parameterized, {Ash.Type.UtcDatetimeUsec.EctoType, precision: :microsecond}}
),
{:parameterized,
{Ash.Type.UtcDatetimeUsec.EctoType,
precision: :microsecond, cast_dates_as: :start_of_day, timezone: :utc}}
),
model:
type(
type(
^{3.004335183048418, 3.0043351830485556, 1.0270002134258505},
{:parameterized, {Ash.Type.Tuple.EctoType, fields: []}}
),
{:parameterized,
{Ash.Type.Tuple.EctoType,
fields: [
alpha: [
description: "The alpha parameter for the beta model",
allow_nil?: true,
constraints: [],
type: Ash.Type.Float
],
beta: [
description: "The beta parameter for the beta model",
allow_nil?: true,
constraints: [],
type: Ash.Type.Float
],
t: [
description: "The half life of the fact in days",
allow_nil?: true,
constraints: [],
type: Ash.Type.Float
]
]}}
)
]
],
select: struct(f0, [:id, :total, :last_review, :successes, :model, :updated_at, :inserted_at])
value `{3.004335183048418, 3.0043351830485556, 1.0270002134258505}` in `update` cannot be cast to type #Ash.Type.Tuple.EctoType<[fields: []]> in query:

from f0 in Katarineko.Learning.Fact,
as: 0,
where: type(
type(as(0).id, {:parameterized, {Ash.Type.Integer.EctoType, []}}),
{:parameterized, {Ash.Type.Integer.EctoType, []}}
) ==
type(
type(^64, {:parameterized, {Ash.Type.Integer.EctoType, []}}),
{:parameterized, {Ash.Type.Integer.EctoType, []}}
),
update: [
set: [
updated_at:
type(
type(
^~U[2025-05-20 11:02:30.068792Z],
{:parameterized, {Ash.Type.UtcDatetimeUsec.EctoType, precision: :microsecond}}
),
{:parameterized,
{Ash.Type.UtcDatetimeUsec.EctoType,
precision: :microsecond, cast_dates_as: :start_of_day, timezone: :utc}}
),
model:
type(
type(
^{3.004335183048418, 3.0043351830485556, 1.0270002134258505},
{:parameterized, {Ash.Type.Tuple.EctoType, fields: []}}
),
{:parameterized,
{Ash.Type.Tuple.EctoType,
fields: [
alpha: [
description: "The alpha parameter for the beta model",
allow_nil?: true,
constraints: [],
type: Ash.Type.Float
],
beta: [
description: "The beta parameter for the beta model",
allow_nil?: true,
constraints: [],
type: Ash.Type.Float
],
t: [
description: "The half life of the fact in days",
allow_nil?: true,
constraints: [],
type: Ash.Type.Float
]
]}}
)
]
],
select: struct(f0, [:id, :total, :last_review, :successes, :model, :updated_at, :inserted_at])
Is it because fields is empty here, maybe?
^{3.004335183048418, 3.0043351830485556, 1.0270002134258505},
{:parameterized, {Ash.Type.Tuple.EctoType, fields: []}}
^{3.004335183048418, 3.0043351830485556, 1.0270002134258505},
{:parameterized, {Ash.Type.Tuple.EctoType, fields: []}}
ZachDaniel
ZachDanielβ€’5d ago
Huh it's losing the constraints somehow? I think this is a bug I'll have to look at It's somewhere in our type casting logic and that is pretty hairy Okay so next steps are to get a reproduction up I can play with
mcoll
mcollOPβ€’5d ago
do you have enough with what I gave you above (my sample code?) (okay, just discovered dbg with iex --dbg pry, pretty nice)
ZachDaniel
ZachDanielβ€’5d ago
If you could add a test in ash_postgres that would be the ideal I've got a lot on my plate today in addition to a cold πŸ₯²
mcoll
mcollOPβ€’5d ago
will try to do it later, gotta work now πŸ™‚ I didn't know what I was getting into by using the tuple type hahaha
ZachDaniel
ZachDanielβ€’5d ago
πŸ˜† yeah its not your fault, I was rushing to get something ready for the AshAI demo and I never went back and closed the loop I'm looking into it now
mcoll
mcollOPβ€’4d ago
oh, I see you merged the PR above! so I guess I'm officialy an Ash contributor ^^ sorry, I haven't had time to create a reproducing test yet πŸ™ between work and my daughter I haven't really found the time
ZachDaniel
ZachDanielβ€’4d ago
its all good it should be fixed now Or at least, I added some tests to postgres for whatever was going on, and made some type-related fixes in Ash that may have resolved the issue but if you're still dealing with it LMK
mcoll
mcollOPβ€’4d ago
oh, so 3.5.11 should already have the fixes for the above issue? will try later today
ZachDaniel
ZachDanielβ€’4d ago
I believe so yes
mcoll
mcollOPβ€’4d ago
upgraded ash and ash_postgres to latest version
mix deps.update ash ash_postgres
mix deps.update ash ash_postgres
They are now at 3.5.11 and 2.5.20 respectively, and I still get the same error trying with a deps.clean first to see if it's a caching problem or smth
ZachDaniel
ZachDanielβ€’4d ago
damn, alright ah, right the problem for you was updating a certain way, nto filtering wasn't it I'll take a look once I get a repro
mcoll
mcollOPβ€’4d ago
I'll try to build a repro for you
trying with a deps.clean first to see if it's a caching problem or smth
same thing
ZachDaniel
ZachDanielβ€’4d ago
you can take a look at the tests in ash_postgres, it should be pretty straightforward to add something there, and there is now a resource in the tests using the tuple type
mcoll
mcollOPβ€’4d ago
the repro should be in ash_postgres right? perfect, yeah, was checking your commit from yesterday @Zach Daniel I cannot reproduce at all :doublefacepalm:
ZachDaniel
ZachDanielβ€’4d ago
πŸ˜“ In your repro, you're up to date on all the relevant packages? ash, ash_postgres, ash_sql?
mcoll
mcollOPβ€’4d ago
ash 3.5.11
ash_postgres 2.5.20
ash_sql 0.2.75
ash 3.5.11
ash_postgres 2.5.20
ash_sql 0.2.75
yes
ZachDaniel
ZachDanielβ€’4d ago
It looks like its an issue doing an atomic update
mcoll
mcollOPβ€’4d ago
I've created the following test trying to replicate as much as possible the situation in ash_postgres
update :review do
change get_and_lock_for_update()

argument :result, :atom do
allow_nil? false
constraints one_of: [:success, :failure]
end

change set_attribute(:datetime, DateTime.utc_now())
change increment(:score), where: [argument_equals(:result, :success)]

change set_attribute(:title, "Tuple Test 2")
change(after_action(fn changeset, record, _context ->
new_model = {1.0, 2.0, 3.0}

record
|> Ash.Changeset.for_update(:update)
|> Ash.Changeset.force_change_attribute(:model, new_model)
|> Ash.update()
end))

require_atomic?(false)
end
update :review do
change get_and_lock_for_update()

argument :result, :atom do
allow_nil? false
constraints one_of: [:success, :failure]
end

change set_attribute(:datetime, DateTime.utc_now())
change increment(:score), where: [argument_equals(:result, :success)]

change set_attribute(:title, "Tuple Test 2")
change(after_action(fn changeset, record, _context ->
new_model = {1.0, 2.0, 3.0}

record
|> Ash.Changeset.for_update(:update)
|> Ash.Changeset.force_change_attribute(:model, new_model)
|> Ash.update()
end))

require_atomic?(false)
end
but it passes πŸ˜…
ZachDaniel
ZachDanielβ€’4d ago
Try doing this:
Resource
|> Ash.Query.filter(id == ^record.id)
|> Ash.bulk_update!(:update, %{model: new_model})
Resource
|> Ash.Query.filter(id == ^record.id)
|> Ash.bulk_update!(:update, %{model: new_model})
Actually, what does that :update action that gets called the second time around look like
mcoll
mcollOPβ€’4d ago
in my case it's defaults [:update] in the Post model from ash_postgres it's
update :update do
primary?(true)
require_atomic?(false)
end
update :update do
primary?(true)
require_atomic?(false)
end
OH if I change my update implementation for that one it also passes so maybe the require_atomic? false in the update changes things (since primary? is set by the default) that's why it passes in the test yes, if I create another
update :atomic_update do
end
update :atomic_update do
end
and then update the change to use that one
record
|> Ash.Changeset.for_update(:atomic_update)
|> Ash.Changeset.force_change_attribute(:updated_at, DateTime.utc_now())
|> Ash.Changeset.force_change_attribute(:model, new_model)
|> Ash.update()
record
|> Ash.Changeset.for_update(:atomic_update)
|> Ash.Changeset.force_change_attribute(:updated_at, DateTime.utc_now())
|> Ash.Changeset.force_change_attribute(:model, new_model)
|> Ash.update()
it fails in ash_postgres with the same error
Invalid Error

* Invalid filter value `{1.0, 2.0, 3.0}` supplied in `#Ecto.Changeset<action: nil, changes: %{}, errors: [], data: #AshPostgres.Test.Post<>, valid?: true, ...>`
Invalid Error

* Invalid filter value `{1.0, 2.0, 3.0}` supplied in `#Ecto.Changeset<action: nil, changes: %{}, errors: [], data: #AshPostgres.Test.Post<>, valid?: true, ...>`
another interesting thing, it doesn't seem to happen with the tuple you created that one works well (maybe because it's a custom type isntead of a literal tuple?)
mcoll
mcollOPβ€’4d ago
GitHub
chore: Create reproduction test of tuple Invalid filter value by Ma...
Contributor checklist Bug fixes include regression tests Features include unit/acceptance tests
mcoll
mcollOPβ€’4d ago
so it seems that it is caused by calling another action that is not atomic? on a literal tuple attribute Im wondering if I should be calling a nested action like this or not, is this expected? Or should I be doing Resource |> Ash.Query.filter(id == ^record.id) |> Ash.bulk_update!(:update, %{model: new_model}) like you say? I don't have time right now to reduce the test even more, hopefully it's a good starting point for further exploration
ZachDaniel
ZachDanielβ€’4d ago
Perfect, I'll look into it πŸ˜„ Thanks for the repro
mcoll
mcollOPβ€’4d ago
for now at least I'm unblocked πŸ™‚

Did you find this page helpful?