Skip to content

validate_required/3 treating empty lists and maps as invalid is a breaking change #4712

@tarzan

Description

@tarzan

Context

Commit cb2ba4d ("Make clear the distinction of emptiness between cast and validate_required") changed validate_required/3 to treat empty lists ([]) and empty maps (%{}) as invalid values, alongside nil and empty strings.

Previously:

If the value of a field is nil or a string made only of whitespace, the changeset is marked as invalid

Now:

If the value of a field is nil or an empty string/array/map, the changeset is marked as invalid

This is listed as an Enhancement in the changelog ("Consider empty lists as empty values by default"), but it silently breaks existing code that relies on validate_required accepting [] or %{} as valid values.

Impact

This affects both application code and third-party libraries. For example:

Oban (v2.17 through v2.20.3) has validate_required([:args]) on its Job schema, where args is a map. Jobs created with %{} args (a common and documented pattern) will fail validation:

# This is documented in Oban and widely used
%{} |> MyWorker.new() |> Oban.insert()
# => {:error, #Ecto.Changeset<errors: [args: {"can't be blank", [validation: :required]}]>}

Application schemas with array or map fields that have [] or %{} as valid (and often default) values will also break:

schema "documents" do
  field :tags, {:array, :string}  # default: []
end

def changeset(doc, attrs) do
  doc
  |> cast(attrs, [:tags])
  |> validate_required([:tags])  # now rejects [] as blank
end

Suggestion

This behavior change should either:

  1. Be listed as a breaking change with a clear migration path, or
  2. Be made opt-in rather than changing the default behavior

The previous behavior (only nil and whitespace strings are considered blank) is a reasonable default that many libraries and applications depend on.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions