Code of Conduct
AI Policy
Versions
elixir 1.19.4-otp-28
erlang 28.2
Operating system
macOS
Current Behavior
Defining Postgrex types like the documentation describes leads to encoding errors when creating resources with ash_oban and multitenancy.
postgrex_types.ex:
Postgrex.Types.define(
MyApp.PostgrexTypes,
[AshPostgres.Extensions.Vector] ++ Ecto.Adapters.Postgres.extensions(),
[]
)
config.exs:
config :my_app, MyApp.Repo, types: MyApp.PostgrexTypes
insight.ex:
defmodule MyApp.Feedback.Insight do
require Ash.Query
use Ash.Resource,
otp_app: :my_app,
domain: MyApp.Feedback,
data_layer: AshPostgres.DataLayer,
extensions: [AshAi, AshOban],
authorizers: [Ash.Policy.Authorizer]
multitenancy do
strategy :context
end
vectorize do
full_text do
name :context_vector
text fn record ->
"""
Name: #{record.name}
Description: #{record.description || ""}
"""
end
used_attributes [:name, :description]
end
strategy :ash_oban
embedding_model MyApp.AI.OpenAIEmbeddingModel
ash_oban_trigger_name :vectorize_insight_trigger
end
oban do
triggers do
trigger :vectorize_insight_trigger do
action :ash_ai_update_embeddings
queue :ash_ai_vectorization
worker_read_action :read
worker_module_name __MODULE__.AshOban.Worker.UpdateEmbeddings
scheduler_module_name __MODULE__.AshOban.Scheduler.UpdateEmbeddings
scheduler_cron false
list_tenants fn -> MyApp.Repo.all_tenants() end
timeout :timer.minutes(1)
max_attempts 3
end
end
end
end
Creating the resource:
insight =
MyApp.Feedback.create_insight!(%{name: "New Insight"},
tenant: socket.assigns.current_tenant # An organization struct
)
Error:
[error] GenServer #PID<0.1777.0> terminating
** (Ash.Error.Unknown)
Bread Crumbs:
> Exception raised in: MyApp.Feedback.Insight.create
Unknown Error
* ** (Protocol.UndefinedError) protocol Jason.Encoder not implemented for MyApp.Accounts.Organization (a struct), Jason.Encoder protocol must always be explicitly implemented.
If you own the struct, you can derive the implementation specifying which fields should be encoded to JSON:
@derive {Jason.Encoder, only: [....]}
defstruct ...
It is also possible to encode all fields, although this should be used carefully to avoid accidentally leaking private information when new fields are added:
@derive Jason.Encoder
defstruct ...
Finally, if you don't own the struct you want to encode to JSON, you may use Protocol.derive/3 placed outside of any module:
Protocol.derive(Jason.Encoder, NameOfTheStruct, only: [...])
Protocol.derive(Jason.Encoder, NameOfTheStruct)
Got value:
%MyApp.Accounts.Organization{
id: "abc7c0ac-1ebd-42d6-8195-3b92081f862f",
name: "Organization",
subdomain: #Ash.CiString<"org">,
logo: "/images/tenant/org_logo.jpg",
inserted_at: ~U[2025-12-05 17:47:32.371315Z],
updated_at: ~U[2025-12-05 17:47:32.371315Z],
user_count: #Ash.NotLoaded<:aggregate, field: :user_count>,
users_join_assoc: #Ash.NotLoaded<:relationship, field: :users_join_assoc>,
organization_memberships: #Ash.NotLoaded<:relationship, field: :organization_memberships>,
users: #Ash.NotLoaded<:relationship, field: :users>,
__meta__: #Ecto.Schema.Metadata<:loaded, "organizations">
}
(jason 1.4.4) lib/jason.ex:213: Jason.encode_to_iodata!/2
(my_app 0.1.0) deps/postgrex/lib/postgrex/type_module.ex:1084: MyApp.PostgrexTypes.encode_params/3
(postgrex 0.21.1) lib/postgrex/query.ex:75: DBConnection.Query.Postgrex.Query.encode/3
(db_connection 2.8.1) lib/db_connection.ex:1446: DBConnection.encode/5
(db_connection 2.8.1) lib/db_connection.ex:1546: DBConnection.run_prepare_execute/5
(db_connection 2.8.1) lib/db_connection.ex:769: DBConnection.parsed_prepare_execute/5
(db_connection 2.8.1) lib/db_connection.ex:761: DBConnection.prepare_execute/4
(ecto_sql 3.13.2) lib/ecto/adapters/postgres/connection.ex:102: Ecto.Adapters.Postgres.Connection.prepare_execute/5
(ecto_sql 3.13.2) lib/ecto/adapters/sql.ex:1004: Ecto.Adapters.SQL.execute!/5
(ecto_sql 3.13.2) lib/ecto/adapters/sql.ex:996: Ecto.Adapters.SQL.execute/6
(ecto 3.13.5) lib/ecto/repo/queryable.ex:241: Ecto.Repo.Queryable.execute/4
(ecto 3.13.5) lib/ecto/repo/queryable.ex:19: Ecto.Repo.Queryable.all/3
(ecto 3.13.5) lib/ecto/repo/queryable.ex:163: Ecto.Repo.Queryable.one/3
(oban 2.20.2) lib/oban/engines/basic.ex:546: Oban.Engines.Basic.fetch_job/3
(oban 2.20.2) lib/oban/engines/basic.ex:433: Oban.Engines.Basic.insert_unique/3
(my_app 0.1.0) lib/my_app/repo.ex:2: anonymous fn/1 in MyApp.Repo."transaction (overridable 1)"/2
(ecto 3.13.5) lib/ecto/repo/transaction.ex:11: anonymous fn/3 in Ecto.Repo.Transaction.transact/4
(ecto_sql 3.13.2) lib/ecto/adapters/sql.ex:1458: anonymous fn/3 in Ecto.Adapters.SQL.checkout_or_transaction/4
(db_connection 2.8.1) lib/db_connection.ex:1046: DBConnection.transaction/3
(oban 2.20.2) lib/oban/repo.ex:156: Oban.Repo.transaction/4
(jason 1.4.4) lib/jason.ex:213: Jason.encode_to_iodata!/2
(my_app 0.1.0) deps/postgrex/lib/postgrex/type_module.ex:1084: MyApp.PostgrexTypes.encode_params/3
(postgrex 0.21.1) lib/postgrex/query.ex:75: DBConnection.Query.Postgrex.Query.encode/3
(db_connection 2.8.1) lib/db_connection.ex:1446: DBConnection.encode/5
(db_connection 2.8.1) lib/db_connection.ex:1546: DBConnection.run_prepare_execute/5
(db_connection 2.8.1) lib/db_connection.ex:769: DBConnection.parsed_prepare_execute/5
(db_connection 2.8.1) lib/db_connection.ex:761: DBConnection.prepare_execute/4
(ecto_sql 3.13.2) lib/ecto/adapters/postgres/connection.ex:102: Ecto.Adapters.Postgres.Connection.prepare_execute/5
(ecto_sql 3.13.2) lib/ecto/adapters/sql.ex:1004: Ecto.Adapters.SQL.execute!/5
(ecto_sql 3.13.2) lib/ecto/adapters/sql.ex:996: Ecto.Adapters.SQL.execute/6
(ecto 3.13.5) lib/ecto/repo/queryable.ex:241: Ecto.Repo.Queryable.execute/4
(ecto 3.13.5) lib/ecto/repo/queryable.ex:19: Ecto.Repo.Queryable.all/3
(ecto 3.13.5) lib/ecto/repo/queryable.ex:163: Ecto.Repo.Queryable.one/3
(oban 2.20.2) lib/oban/engines/basic.ex:546: Oban.Engines.Basic.fetch_job/3
(oban 2.20.2) lib/oban/engines/basic.ex:433: Oban.Engines.Basic.insert_unique/3
(my_app 0.1.0) lib/my_app/repo.ex:2: anonymous fn/1 in MyApp.Repo."transaction (overridable 1)"/2
(ecto 3.13.5) lib/ecto/repo/transaction.ex:11: anonymous fn/3 in Ecto.Repo.Transaction.transact/4
(ecto_sql 3.13.2) lib/ecto/adapters/sql.ex:1458: anonymous fn/3 in Ecto.Adapters.SQL.checkout_or_transaction/4
(db_connection 2.8.1) lib/db_connection.ex:1046: DBConnection.transaction/3
(oban 2.20.2) lib/oban/repo.ex:156: Oban.Repo.transaction/4
I'm unsure how to debug this one - or where the right place for a fix would be. Any guidance?
Reproduction
No response
Expected Behavior
No response
Code of Conduct
AI Policy
Versions
elixir 1.19.4-otp-28
erlang 28.2
Operating system
macOS
Current Behavior
Defining Postgrex types like the documentation describes leads to encoding errors when creating resources with ash_oban and multitenancy.
postgrex_types.ex:config.exs:insight.ex:Creating the resource:
Error:
I'm unsure how to debug this one - or where the right place for a fix would be. Any guidance?
Reproduction
No response
Expected Behavior
No response