Skip to content

Ash Reactor is wrapping error tuples in Ash.Error.Unknown.UnknownError #2506

@katipber

Description

@katipber

Code of Conduct

  • I agree to follow this project's Code of Conduct

AI Policy

  • I agree to follow this project's AI Policy, or I agree that AI was not used while creating this issue.

Versions

Erlang/OTP 27 [erts-15.2.7.4] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit]

Elixir 1.19.4 (compiled with Erlang/OTP 27)

Operating system

macOS Sequoia

Current Behavior

Error tuples within Ash.Reactor are getting wrapped in the message of Ash.Error.Unknown.UnknownError.

For example an error tuple returned from a dummy step like this one:

defmodule Foo.Reactor.Atom do
  use Ash.Reactor

  step :first do
    run(fn _, _ ->
      {:error, :error_atom}
    end)
  end
end

Ends up wrapped like this:

{:error,
 %Ash.Error.Unknown{
   errors: [
     %Ash.Error.Unknown.UnknownError{
       error: "** (Reactor.Error.Invalid) \nInvalid Error\n\n* # Run Step Error\n\nAn error occurred while attempting to run the `:first` step.\n\n## `step`:\n\n%Reactor.Step{arguments: [], async?: true, context: %{}, description: nil, impl: {Reactor.Step.AnonFn, [run: &Foo.Reactor.Atom.run_0_generated_27DAC62021118441FC2A7B9C099E2271/2, compensate: nil, undo: nil, backoff: nil]}, name: :first, max_retries: :infinity, ref: :first, transform: nil, guards: []}\n\n## `error`:\n\n`:error_atom`\n\n  (reactor 0.17.0) lib/reactor/error/invalid/run_step_error.ex:8: Reactor.Error.Invalid.RunStepError.exception/1\n  (reactor 0.17.0) lib/reactor/executor/step_runner.ex:212: Reactor.Executor.StepRunner.handle_run_result/5\n  (reactor 0.17.0) lib/reactor/executor/step_runner.ex:165: Reactor.Executor.StepRunner.do_run/4\n  (reactor 0.17.0) lib/reactor/executor/step_runner.ex:53: Reactor.Executor.StepRunner.run/4\n  (reactor 0.17.0) lib/reactor/executor/step_runner.ex:74: Reactor.Executor.StepRunner.run_async/5\n  (elixir 1.19.4) lib/task/supervised.ex:105: Task.Supervised.invoke_mfa/2\n  (elixir 1.19.4) lib/task/supervised.ex:40: Task.Supervised.reply/4",
       field: nil,
       value: nil,
       splode: Ash.Error,
       bread_crumbs: [],
       vars: [],
       path: [],
       stacktrace: #Splode.Stacktrace<>,
       class: :unknown
     }
   ]
 }}

Same for returning custom errors, or raising custom exceptions. You can check them in reproduction part.

Reproduction

Clone repo:
git clone https://github.com/katipber/mantis.git

Checkout to bug branch:
git checkout ash-reactor-error

Open ash_reactor_error folder in devcontainer or you may need to setup right Elixir versions locally.

Get dependencies:
mix deps.get

Start shell:
iex -S mix

To see the wrapped up errors for each error tuple run related codes in shell:
{:error, :atom} -> Foo.return_atom
{:error, CustomError} -> Foo.return_error
raise CustomError ... -> Foo.raise_exception

Note: raising exception is not the way I would like to go, it is here just to showcase wrapping issue.

Expected Behavior

I was expecting to pattern match or somehow identify different error types without string parsing.

Eg:

case Foo.return_atom do
    {:error, :atom} -> "Atom returned"
    {:error, %CustomError{}} -> "Custom error returned"
end

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions