Central mapping from error atoms (returned by the Publishing module's public API) to translated human-readable strings.
Keeping the API layer locale-agnostic means callers and integration
consumers can pattern-match on atoms and decide their own presentation.
Anything user-facing (flash messages, error banners) goes through
message/1 which wraps each mapping in gettext/1 using the
PhoenixKitWeb.Gettext backend.
Supported reason shapes
- plain atoms —
:not_found,:slug_already_exists,:title_required,:invalid_mode,:no_published_version, etc. - tagged tuples —
{:ai_translation_failed, reason},{:ai_extract_failed, reason},{:ai_request_failed, reason},{:source_post_read_failed, reason} - strings — passed through unchanged (legacy / interpolated messages)
- unknown reasons — rendered as
"Unexpected error: <inspect>"via gettext so nothing ever silently surfaces a raw struct
Log-safe error inspection
truncate_for_log/2 is the canonical way to render an opaque error
reason inside Logger.* calls that target external HTTP responses or
large AI payloads. It coerces the value to a string via inspect/1
and clips it to a fixed character budget so a runaway response body
never floods the logs.
Example
iex> PhoenixKit.Modules.Publishing.Errors.message(:not_found)
"Not found"
iex> PhoenixKit.Modules.Publishing.Errors.message({:ai_translation_failed, :timeout})
"AI translation failed: :timeout"
Summary
Types
Atoms returned by Publishing's public API on error.
Tagged-tuple errors that carry a downstream reason.
Functions
Translates an error reason (atom, tagged tuple, or string) into a user-facing string via gettext.
Renders any error reason as a log-safe string clipped to max chars.
Types
@type error_atom() ::
:already_exists
| :cache_miss
| :cannot_delete_live
| :conflicts_with_post_slug
| :db_update_failed
| :destination_exists
| :group_not_found
| :invalid_content
| :invalid_format
| :invalid_mode
| :invalid_name
| :invalid_path
| :invalid_slug
| :invalid_status
| :invalid_type
| :invalid_version
| :last_language
| :last_version
| :no_post
| :no_published_version
| :no_uuid
| :not_found
| :not_published
| :post_not_found
| :post_trashed
| :reserved_language_code
| :reserved_route_word
| :slug_already_exists
| :slug_taken
| :title_required
| :unpublished
| :version_access_disabled
| :ai_disabled
| :ai_no_prompt
| :ai_endpoint_not_found
| :ai_endpoint_disabled
Atoms returned by Publishing's public API on error.
@type tagged_error() :: {:ai_translation_failed, term()} | {:ai_extract_failed, term()} | {:ai_request_failed, term()} | {:source_post_read_failed, term()}
Tagged-tuple errors that carry a downstream reason.
Functions
@spec message(error_atom() | tagged_error() | term()) :: String.t()
Translates an error reason (atom, tagged tuple, or string) into a user-facing string via gettext.
@spec truncate_for_log(term(), pos_integer()) :: String.t()
Renders any error reason as a log-safe string clipped to max chars.
Use inside Logger.* calls that may include external HTTP response
bodies, AI completions, or other unbounded payloads — without the
cap a single failed AI request can flood logs with tens of KB.
Returns the inspected form unchanged when it fits, or appends an ellipsis hint when truncated.