Validation failing only with AshPostgres, works as expected without a data_layer

The update works fine in postgres if I remove the validate block

Github repo just in case: GitHub - albinkc/helpdesk

Deps:

  {:ash, "~> 3.0.0-rc.27"},
  {:picosat_elixir, "~> 0.2"},
  {:ash_postgres, "~> 2.0.0-rc.7"},
# lib/helpdesk/support/ticket.ex

defmodule Helpdesk.Support.Ticket do
  use Ash.Resource,
    domain: Helpdesk.Support,
    data_layer: AshPostgres.DataLayer

  postgres do
    table "tickets"
    repo Helpdesk.Repo
  end

  actions do
    defaults [:read]

    create :open do
      accept [:subject]
    end

    update :close do
      accept []

      validate attribute_does_not_equal(:status, :closed) do
        message "Ticket is already closed"
      end

      change set_attribute(:status, :closed)
    end
  end

  attributes do
    uuid_primary_key :id

    attribute :subject, :string do
      allow_nil? false
      public? true
    end

    attribute :status, :atom do
      constraints one_of: [:open, :closed]
      default :open
      allow_nil? false
    end
  end
end

Without data_layer:

iex(1)> ticket = (  Helpdesk.Support.Ticket  |> Ash.Changeset.for_create(:open, %{subject: "My mouse won't click!"})  |> Ash.create!())
#Helpdesk.Support.Ticket<
  __meta__: #Ecto.Schema.Metadata<:built, "">,
  id: "f19145dd-4a29-4821-82ae-1a5c3d258686",
  subject: "My mouse won't click!",
  status: :open,
  aggregates: %{},
  calculations: %{},
  ...
>

Try closing twice to trigger validation (works as expected)

iex(2)> ticket|> Ash.Changeset.for_update(:close)|> Ash.update!() |> Ash.Changeset.for_update(:close)|> Ash.update!()
** (Ash.Error.Invalid) Invalid Error

* Invalid value provided for status: Ticket is already closed.

:closed

  (elixir 1.16.2) lib/process.ex:860: Process.info/2
  (ash 3.0.0-rc.27) lib/ash/error/changes/invalid_attribute.ex:5:
  ...

With postgres:

iex(1)> ticket = (  Helpdesk.Support.Ticket  |> Ash.Changeset.for_create(:open, %{subject: "My mouse won't click8!"})  |> Ash.create!())

08:26:56.992 [debug] QUERY OK db=1.5ms idle=918.1ms
begin []

08:26:57.023 [debug] QUERY OK source="tickets" db=5.7ms
INSERT INTO "tickets" ("id","status","subject") VALUES ($1,$2,$3) RETURNING "status","subject","id" ["d93e9274-7f9a-4af2-b57f-b73f62c96e13", :open, "My mouse won't click8!"]

08:26:57.028 [debug] QUERY OK db=1.5ms
commit []
#Helpdesk.Support.Ticket<
  __meta__: #Ecto.Schema.Metadata<:loaded, "tickets">,
  id: "d93e9274-7f9a-4af2-b57f-b73f62c96e13",
  subject: "My mouse won't click8!",
  status: :open,
  aggregates: %{},
  calculations: %{},
  ...
>

Running the update

iex(2)> ticket|> Ash.Changeset.for_update(:close)|> Ash.update!()
** (Ash.Error.Unknown) Unknown Error

* %KeyError{key: :atomics, term: {:not_atomic, "Failed to validate expression error(Ash.Error.Changes.InvalidAttribute,  %{message: \"Ticket is already closed\", value: type(:closed,  Ash.Type.Atom,  [one_of: [:open, :closed]]), vars: %{value: :closed, field: :status}, field: :status}): \"data layer does not support the function error(Ash.Error.Changes.InvalidAttribute, %{message: \\\"Ticket is already closed\\\", value: :closed, vars: %{value: :closed, field: :status}, field: :status})\""}, message: "key :atomics not found in: {:not_atomic,\n \"Failed to validate expression error(Ash.Error.Changes.InvalidAttribute,  %{message: \\\"Ticket is already closed\\\", value: type(:closed,  Ash.Type.Atom,  [one_of: [:open, :closed]]), vars: %{value: :closed, field: :status}, field: :status}): \\\"data layer does not support the function error(Ash.Error.Changes.InvalidAttribute, %{message: \\\\\\\"Ticket is already closed\\\\\\\", value: :closed, vars: %{value: :closed, field: :status}, field: :status})\\\"\"}\n\nIf you are using the dot syntax, such as map.field, make sure the left-hand side of the dot is a map"}
  (ash 3.0.0-rc.27) lib/ash/changeset/changeset.ex:2110: Ash.Changeset.extract_atomic_eager_errors/3
  (ash 3.0.0-rc.27) lib/ash/changeset/changeset.ex:2093: Ash.Changeset.hydrate_atomic_refs/3
  (ash 3.0.0-rc.27) lib/ash/actions/update/update.ex:66: Ash.Actions.Update.run/4
  (ash 3.0.0-rc.27) lib/ash.ex:2351: Ash.update/2
  (ash 3.0.0-rc.27) lib/ash.ex:2329: Ash.update!/2
  (elixir 1.16.2) src/elixir.erl:405: :elixir.eval_external_handler/3
  (stdlib 5.2) erl_eval.erl:750: :erl_eval.do_apply/7
  (elixir 1.16.2) src/elixir.erl:378: :elixir.eval_forms/4
    (ash 3.0.0-rc.27) lib/ash/changeset/changeset.ex:2110: Ash.Changeset.extract_atomic_eager_errors/3
    (ash 3.0.0-rc.27) lib/ash/changeset/changeset.ex:2093: Ash.Changeset.hydrate_atomic_refs/3
    (ash 3.0.0-rc.27) lib/ash/actions/update/update.ex:66: Ash.Actions.Update.run/4
    (ash 3.0.0-rc.27) lib/ash.ex:2351: Ash.update/2
    (ash 3.0.0-rc.27) lib/ash.ex:2329: Ash.update!/2
    iex:2: (file)

What seems to be the issue here? Thanks in advance.

This is definitely a bug. Can you please open an issue on ash? I will address later today.

1 Like

Created issue on ash-project/ash

1 Like