Unique constraint not working in Phoenix app

I have a simple app that I want to add unique constraint to one of the field. Even after I have created index in migration file and the unique_constraint in schema, errors show that I do not have any constraint in changeset.


defmodule TestUniqueConstraint.Shop.Product do
  use Ecto.Schema
  import Ecto.Changeset

  schema "products" do
    field :email, :string


  @doc false
  def changeset(product, attrs) do
    |> cast(attrs, [:email])
    |> validate_required([:email])
    |> unique_constraint(:email)

migration file

defmodule TestUniqueConstraint.Repo.Migrations.CreateProducts do
  use Ecto.Migration

  def change do
    create table(:products) do
      add :email, :string


    create unique_index(:products, [:email])

Error shown after adding the same product with same email twice:

** (Ecto.ConstraintError) constraint error when attempting to insert struct:

    * products_email_index (unique_constraint)

If you would like to stop this constraint violation from raising an 
exception and instead add it as an error to your changeset, please
call `unique_constraint/3` on your changeset with the constraint
`:name` as an option.

The changeset has not defined any constraint.

    (ecto 3.5.8) lib/ecto/repo/schema.ex:688: anonymous fn/4 in Ecto.Repo.Schema.constraints_to_errors/3
    (elixir 1.11.2) lib/enum.ex:1399: Enum."-map/2-lists^map/1-0-"/2
    (ecto 3.5.8) lib/ecto/repo/schema.ex:673: Ecto.Repo.Schema.constraints_to_errors/3
    (ecto 3.5.8) lib/ecto/repo/schema.ex:654: Ecto.Repo.Schema.apply/4
    (ecto 3.5.8) lib/ecto/repo/schema.ex:262: anonymous fn/15 in Ecto.Repo.Schema.do_insert/4
    (ecto 3.5.8) lib/ecto/repo/schema.ex:164: Ecto.Repo.Schema.insert!/4

Are there any steps I have missed?

Does your code call the changeset function? I have run into this before where I was calling Repo.delete with a struct directly and not a changeset.

That’s right. I have been writing seeds file and using Repo.insert directly with a struct. When I test it manually, I entirely forgot about using the changeset function. That works now. Thanks!

You’re welcome. Easy to miss!