(KeyError) key :action not found ... but I can see :action in changeset

I’m getting a weird error. It says :action can’t be found … but I can see it in the changeset (see error code below). I haven’t removed :action anywhere in my code. It gets set in the handle_event(“validate” …) function below (which I got from Phoenix LiveView examples).

What could be causing this? I haven’t run this particular piece of code since I upgraded LiveView. Did something change in the update regarding setting :action?

You can see below that :action is set to :validate. I don’t understand why it can’t see that. The form seems to process everything correctly for validation, but it throws this error when I go to save the new group.

** (KeyError) key :action not found in: %{__changed__: %{}, changeset: #Ecto.Changeset<action: :validate, changes: %{city: "Santa Cruz", country: "United States" ...

The handle_event function where :action is normally set. I just followed all of the examples for this and I don’t change :action anywhere in my code, so I don’t understand why it’s choking on this.

def handle_event("validate", %{"group" => group_params}, socket) do
    changeset =
      |> Groups.change_group(group_params)
      |> Map.put(:action, :validate)
    {:noreply, assign(socket, :changeset, changeset)}

This looks like an error from a LV template, telling you it can’t find :action in the assigns. Which is true: action isn’t an assign, changeset is. You should be able to access action in your template via @changeset.action

But here’s the weird thing. I don’t set :action in my templates. It is used by something related to Phoenix LiveView but I can’t find any documentation on it. Forms that I created months ago suddenly don’t work. None of them changed. It all happens when I go to “Save” the form. Validating works, but saving does not. They were all auto-generated and developed on an older version of LiveView. Something happened when I upgraded to 0.17.

I would set :action in assigns … but I don’t know what to set it to. It must be something used in the new version but I have no idea what to assign to it. Based on previous auto-generated code, the only time I saw :action set was in handle_event(“validate” …). I never changed that. Do you know where :action is being used? Or what values it is looking for?

I figured it out. The auto-generation has a very subtle difference when generating a LiveView versus a Component.

For a LIVEVIEW, handle event uses live_action:

def handle_event("save", %{"group" => group_params}, socket) do
    save_group(socket, socket.assigns.live_action, group_params)

For the LiveView COMPONENT, handle event uses just action:

def handle_event("save", %{"author" => author_params}, socket) do
    save_author(socket, socket.assigns.action, author_params)

When I converted a Component into a Liveview, I completely missed that subtle difference. Those are always the fun bugs to chase down. Sigh.

Thanks for the help @trisolaran. You pointed me in the right direction. :slight_smile: