Skip to content

Fixes #39619 - Prevent ArgumentError when find_by_attributes receives all nil values - #11155

Open
amolpati30 wants to merge 1 commit into
theforeman:developfrom
amolpati30:Prevent_ArgumentError_when_find_by_attributes_receives_nil_values
Open

Fixes #39619 - Prevent ArgumentError when find_by_attributes receives all nil values#11155
amolpati30 wants to merge 1 commit into
theforeman:developfrom
amolpati30:Prevent_ArgumentError_when_find_by_attributes_receives_nil_values

Conversation

@amolpati30

Copy link
Copy Markdown

Inside find_by_attributes, .compact strips all nils: where_attributes = {}

Operatingsystem.find_by_attributes(...) which calls generate_title(description:, name:, major:, minor:). When facts are empty, all values are nil, .compact strips them, and generate_title gets called missing required name: and major: keywords → ArgumentError.

That one line (return none if ...) makes it safe — when everything is nil, it returns an empty result set instead of all records.
ensures generate_title always receives all 4 keywords (even if nil), so it never crashes.

The steps to reproduce are mentioned in the Jira - SAT-46471

@amolpati30 amolpati30 changed the title Prevent ArgumentError when find_by_attributes receives all nil values Fixes #39619 - Prevent ArgumentError when find_by_attributes receives all nil values Aug 13, 2026
@amolpati30
amolpati30 force-pushed the Prevent_ArgumentError_when_find_by_attributes_receives_nil_values branch from 2941a2f to 3bb3327 Compare August 13, 2026 12:25
scope = where(where_attributes)
scope = scope.or(where(description: description)) if description.present?
scope.or(where(title: generate_title(**where_attributes.merge(description: description))))
scope.or(where(title: generate_title(**attributes.merge(description: description))))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generate_title() could still contains nil value even after you pass where_attributes.empty?. Consider changing this to use 'where_attributes' instead-

Suggested change
scope.or(where(title: generate_title(**attributes.merge(description: description))))
scope.or(where(title: generate_title(**where_attributes.merge(description: description))))

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where_attributes.empty? does not consider nil values because I am using .compact before that, which removes any nil values when the user chooses not to gather facts.

"title".freeze
end

def generate_title(description:, name:, major:, minor:)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend updating generate_title() to accept optional keyword arguments as to prevent similar crashes:

Suggested change
def generate_title(description: nil, name: nil, major: nil, minor: nil)

The methods it calls (to_label, fullname) already handle nil gracefully, so my thinking is this would also prevents similar ArgumentError crashes from other code paths while keeping the primary protection, from the way you did at L13

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it will handle the value in the generate_title method via **attributes.merge(description: description). If I don't pass the fact, it will be black, so there is no need to mention it here, as it is already covered above.

@lzap

lzap commented Aug 21, 2026

Copy link
Copy Markdown
Member

There is a clear error thrown, and clear reproducer. I would really love to see a unit test that confirms that, preferably in a separate commit.

The patch mixes some refactoring that is not needed (where_attributes > attributes), would you mind either dropping that, or moving this into another separate commit?

@amolpati30
amolpati30 force-pushed the Prevent_ArgumentError_when_find_by_attributes_receives_nil_values branch from 3bb3327 to e4a7478 Compare September 1, 2026 10:57
@amolpati30

Copy link
Copy Markdown
Author

There is a clear error thrown, and clear reproducer. I would really love to see a unit test that confirms that, preferably in a separate commit.

The patch mixes some refactoring that is not needed (where_attributes > attributes), would you mind either dropping that, or moving this into another separate commit?

The refactor fixes the issue. I tested it both with and without fact gathering, and the proposed fix does not throw any errors. I would prefer to add the unit test in the same commit rather than creating a separate commit for it.

@lzap

lzap commented Sep 1, 2026

Copy link
Copy Markdown
Member

I would prefer to add the unit test in the same commit rather than creating a separate commit for it.

This is okay, I can test this separately.

@lzap lzap left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please simplify the patch to the bare minimum.

The current proposal returns none if some conditions match. This is a behavioral change from what this used to do before the refactoring in #10789 I think. I would probably just call the generate_title if the required arguments (3) are present. @ShimShtein ?

# Find all operatingsystems that are duplicates of the given operating system according to all unique constraints
def find_by_attributes(name: nil, major: nil, minor: nil, description: nil)
where_attributes = {
attributes = {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you drop this rename from the patch and keep it minimal?

assert_empty result
end
end
test "find_by_attributes should return none when all attributes are nil" do

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing newline between the tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants