Using `exists()` in policy with syntax error produces very obtuse stack trace
- Dominant language
- Elixir
- Stars
- 2.5k
- Forks
- 422
- Avg merge
- 23h 26m
- Merged PRs (30d)
- 46
Description
### 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.
### Versions
main
### Operating system
All
### Current Behavior
Broken syntax inside `exists()` like for example:
`exists(foo.bar == "bar")` as opposed to correct syntax `exists(foo, bar == "bar")` gives an obtuse stack trace that gives no information about whats wrong:
```[error] 082eebac-545b-48b4-bb58-2671c09ef121: Exception raised while resolving query.
** (Ash.Error.Unknown)
Bread Crumbs:
> Exception raised in: Safari.Outcrop.PaleoMap.read
> Exception raised in: Safari.Outcrop.Outcrop.read
Unknown Error
* ** (ArgumentError) `nil` is not a Spark DSL module.
nil.persisted(:data_layer)
(spark 2.2.67) lib/spark/dsl/extension.ex:138: Spark.Dsl.Extension.persisted!/3
(ash 3.5.25) lib/ash/filter/filter.ex:3881: Ash.Filter.do_hydrate_refs/2
(ash 3.5.25) lib/ash/filter/filter.ex:3763: Ash.Filter.do_hydrate_refs/2
(safari 0.1.0) lib/safari/policy/end_user_read_access.ex:2: Safari.Policy.EndUserReadAccess.try_strict_check/3
(ash 3.5.25) lib/ash/policy/policy.ex:183: Ash.Policy.Policy.fetch_or_strict_check_fact/2
(ash 3.5.25) lib/ash/policy/policy.ex:427: Ash.Policy.Policy.handle_constants/2
(ash 3.5.25) lib/ash/policy/policy.ex:390: Ash.Policy.Policy.handle_constants/2
(ash 3.5.25) lib/ash/policy/policy.ex:402: Ash.Policy.Policy.handle_constants/2
(ash 3.5.25) lib/ash/policy/policy.ex:390: Ash.Policy.Policy.handle_constants/2
(ash 3.5.25) lib/ash/policy/policy.ex:29: Ash.Policy.Policy.solve/1
(ash 3.5.25) lib/ash/policy/checker.ex:65: Ash.Policy.Checker.strict_check_scenarios/1
(ash 3.5.25) lib/ash/policy/authorizer/authorizer.ex:1724: Ash.Policy.Authorizer.strict_check_result/2
(ash 3.5.25) lib/ash/policy/authorizer/authorizer.ex:693: Ash.Policy.Authorizer.strict_check/2
(ash 3.5.25) lib/ash/can.ex:600: anonymous fn/5 in Ash.Can.run_check/4
(elixir 1.17.2) lib/enum.ex:4858: Enumerable.List.reduce/3
(elixir 1.17.2) lib/enum.ex:2585: Enum.reduce_while/3
(ash 3.5.25) lib/ash/can.ex:597: Ash.Can.run_check/4
(ash 3.5.25) lib/ash/can.ex:198: Ash.Can.can/4
(ash 3.5.25) lib/ash.ex:1807: Ash.can/3
nil.persisted(:data_layer)
(spark 2.2.67) lib/spark/dsl/extension.ex:138: Spark.Dsl.Extension.persisted!/3
(ash 3.5.25) lib/ash/filter/filter.ex:3881: Ash.Filter.do_hydrate_refs/2
(ash 3.5.25) lib/ash/filter/filter.ex:3763: Ash.Filter.do_hydrate_refs/2
(safari 0.1.0) lib/safari/policy/end_user_read_access.ex:2: Safari.Policy.EndUserReadAccess.try_strict_check/3
(ash 3.5.25) lib/ash/policy/policy.ex:183: Ash.Policy.Policy.fetch_or_strict_check_fact/2
(ash 3.5.25) lib/ash/policy/policy.ex:427: Ash.Policy.Policy.handle_constants/2
(ash 3.5.25) lib/ash/policy/policy.ex:390: Ash.Policy.Policy.handle_constants/2
(ash 3.5.25) lib/ash/policy/policy.ex:402: Ash.Policy.Policy.handle_constants/2
(ash 3.5.25) lib/ash/policy/policy.ex:390: Ash.Policy.Policy.handle_constants/2
(ash 3.5.25) lib/ash/policy/policy.ex:29: Ash.Policy.Policy.solve/1
(ash 3.5.25) lib/ash/policy/checker.ex:65: Ash.Policy.Checker.strict_check_scenarios/1
(ash 3.5.25) lib/ash/policy/authorizer/authorizer.ex:1724: Ash.Policy.Authorizer.strict_check_result/2
(ash 3.5.25) lib/ash/policy/authorizer/authorizer.ex:693: Ash.Policy.Authorizer.strict_check/2
(ash 3.5.25) lib/ash/can.ex:600: anonymous fn/5 in Ash.Can.run_check/4
(elixir 1.17.2) lib/enum.ex:4858: Enumerable.List.reduce/3
(elixir 1.17.2) lib/enum.ex:2585: Enum.reduce_while/3
(ash 3.5.25) lib/ash/can.ex:597: Ash.Can.run_check/4
(ash 3.5.25) lib/ash/can.ex:198: Ash.Can.can/4
(ash 3.5.25) lib/ash.ex:1807: Ash.can/3
```
### Reproduction
Just make an invalid exists.
### Expected Behavior
Invalid exists either gives stack trace with information that the exists is wrongly done or it errors already at compile time.
Contributor guide
Research direction
Reproduce the invalid `exists(foo.bar == "bar")` policy and trace the failure through `lib/ash/filter/filter.ex` at `do_hydrate_refs/2`, then through the policy stack shown in the report. Compare it with the valid two-argument form and inspect existing filter or policy coverage. Done means the invalid form reports the malformed `exists` clearly or fails during compilation instead of producing the shown `nil.persisted(:data_layer)` trace.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- elixir
- Domain
- backend-api-design
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100