<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="253399" data-post-id="253399">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Valian" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Valian/120/25479_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Valian
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Personally, a convention that works best for me is</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">:ok | {:ok, value} | {:error, exception}
</code></pre>
<p>where the exception is well-defined as</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyApp.Error do
  @type t :: %__MODULE__{code: atom(), details: binary() | Ecto.Changeset.t()}
  defexception [:code, :details]

  def make(code, details), do: %__MODULE__{code: code, details: details}
end
</code></pre>
<p>I’m using it universally in the whole application. I even wrapped <code>Ecto.Repo</code> return values to follow that convention. The reason why it works so well for me is that I freakin’ love <code>with</code> statement and that structure lets me easily decide if I can handle an error or not. If not, I let the error bubble up, so eventually, it reaches a generic error handler presenting an error to the end-user. <code>code</code> is used in pattern matching, <code>details</code> is a sensible message I can eventually present.</p>
<p>For example</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">with {:ok, user} &lt;- Users.get_user(id),
     {:ok, order} &lt;- Orders.get_order(order_id),
     :ok &lt;- Orders.confirm_order(user, order):
       ...
else:
      {:error, %{code: :not_found}} -&gt; handle_not_found_error(),
      # unexpected errors usually simply bubbles up.
end
</code></pre>
<p>The generic handler only returns known errors to the users, replacing all the unknown ones with a generic one</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  @possible_create_errors [
    :token_invalid,
    :token_expired,
    :params_invalid
  ]

  def create(conn, params) do
    hide_unknown_errors @possible_create_errors do
      with {:ok, data} &lt;- validate_params(real_session_params(params)),
           {:ok, session} &lt;- Sessions.create_real_game_session(params, data.endpoint_id) do
        render(conn, "detail.json", %{record: session})
      end
    end
  end
</code></pre>
<p><code>hide_unknown_errors</code> is a simple macro logging an error if it was unexpected and replacing it with a generic one. It’s a Phoenix app, so I’m defining <code>action_fallback</code> rendering error to the user.</p>
<p>All in all, it works well for me, so I thought I could share <img src="https://forum.elixirforum.com/images/emoji/apple/upside_down_face.png?v=15" title=":upside_down_face:" class="emoji" alt=":upside_down_face:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="253399" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/what-are-your-recommendations-on-method-signatures-and-return-values/48314/42">Post #41</a>
	                </div>
	            </div>
              <div id="likers-container-253399" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="253399"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>