Rules for nested data not applying if parent schema has errors on other nodes

I’m having some issues to make a contract work. Here is a sample code:

class UserContract < Dry::Validation::Contract
  params do
    required(:book).value(:string)

    required(:user).hash do
      required(:name).value(:string)
      required(:email).value(:string)
      required(:age).value(:integer)
    end
  end

  rule("user.name") do
    key.failure('user name failure')
  end

  rule(:book) do
    key.failure('book failure')
  end
end

Here are some scenarios with what I expect or not:

Scenario 1

> UserContract.new.call(book: "Book").errors.to_h
> {:user=>["is missing"], :book=>["book failure"]}

In this case that is what I would expect, since user is missing and I have a rule applying that to book

Scenario 2

> UserContract.new.call(book: "Book", user: { name: "User name", email: "email@example.com", age: 40 }).errors.to_h
> {:user=>{:name=>["user name failure"]}, :book=>["book failure"]}

In this case, that is also what I would expect, since both my rules are applying errors to fields that are present

Scenario 3

> UserContract.new.call(book: "Book", user: { name: "User name", email: "email@example.com" }).errors.to_h
> {:user=>{:age=>["is missing"]}, :book=>["book failure"]}

This is where I’m having issues. I would expect to also have a :name=>["user name failure"] error under user, since the name is filled.

What seems to be happening is that since age is not filled, it is preventing any rule for other user nodes to run.

Is this a bug? I would not expect that to prevent rules from running since user.name is filled correctly.

Yes. Please report an issue.