ash
ash copied to clipboard
Improving error messages when embedded resources have validation issues
Code of Conduct
- [x] I agree to follow this project's Code of Conduct
AI Policy
- [x] I agree to follow this project's AI Policy, or I agree that AI was not used while creating this issue.
Is your feature request related to a problem? Please describe.
Yes. When an Ash.update action is performed on a resource containing an embedded resource with invalid data, the framework returns a cryptic and misleading %Ash.Error.Query.InvalidFilterValue{} error.
This error message is problematic because it:
- Fails to identify which embedded resource or specific field has the validation issue.
- Does not provide the actual validation error message (e.g., "must be present").
- Obscures the root cause, which is that the embedded resource was created using struct/2, bypassing its validations, and the error only surfaces much later during the parent resource's update.
This leads to a confusing and time-consuming debugging process.
Describe the solution you'd like
I propose a two-part solution:
- Improve Error Messages: Enhance the error reporting for embedded resource validations. Instead of a generic InvalidFilterValue error, the error should be more specific, ideally pinpointing the embedded resource type, the field that failed validation, and the reason for the failure.
- Enhance Documentation: Update the official Ash documentation on embedded resources to include a "Validation Best Practices" section. This section should explicitly warn against creating embedded resources with struct/2 without prior validation and recommend using Ash.Changeset.for_create/3 to validate the data first. A clear code example showing the recommended "validate first" approach versus the problematic direct struct creation would be very helpful.
This is an example that could be added to embedded resources documentation (maybe also in to the usage-rules):
## Validation Best Practices
When creating embedded resource structs programmatically, always validate the
data first:
### Avoid: Direct struct creation
```elixir
# This bypasses validation and can cause cryptic errors later
embedded = struct(MyEmbeddedResource, user_data)
```
### Recommended: Validate first
```elixir
case Ash.Changeset.for_create(MyEmbeddedResource, :create, user_data) do
%{valid?: true} ->
embedded = struct(MyEmbeddedResource, user_data) # Now safe
# proceed with your logic
%{valid?: false} = changeset ->
# Handle clear validation errors immediately
errors = Enum.map(changeset.errors, fn error ->
"#{error.field}: #{error.message}"
end)
end
```
Describe alternatives you've considered
No response
Additional context
I've created a livebook with a minimal reproduction and fix this issue
🤔 I think this may be an "edge" case around atomic updates. Could you create a test/reproduction showing this happening?