Elixir version
Elixir 1.20.1 (compiled with Erlang/OTP 29), Erlang/OTP 29 (erts 17.0.2)
Database and Version
PostgreSQL 18.6
Ecto Versions
ecto 3.14.2, ecto_sql 3.14.0
Database Adapter and Versions (postgrex, myxql, etc)
postgrex 0.22.4
Current behavior
Found by an AI assistant working with a human who was fuzz-testing their own application; reduced to the following. Present on master at 24f914a (checked 2026-09-15).
No repo or database is needed for inspect/1:
defmodule P do
use Ecto.ParameterizedType
def type(_), do: :string
def init(opts), do: opts
def cast(v, _), do: {:ok, v}
def load(v, _, _), do: {:ok, v}
def dump(v, _, _), do: {:ok, v}
end
import Ecto.Query
type = {:parameterized, {P, [match: {Foo, :cache, ["^[a-z]+$", []]}]}}
inspect(from p in "posts", where: p.title == type(^"abc", ^type), select: p.id)
The same tuple in an ordinary interpolated value reproduces it with a built-in type and no parameterized type:
Repo.all(from p in "posts", where: p.title == type(^{Foo, :cache, ["a", []]}, :string))
The three-tuple is how Spark stores a match: regex constraint ({Spark.Regex, :cache, [source, opts]}) and Ash's SQL layer copies a type's constraints into the Ecto type parameters, which is how it was hit; neither library is needed to reproduce.
inspect(query)
# "#Inspect.Error<got FunctionClauseError with message: no function clause matching in Access.get/3 ...>"
Repo.all(query)
# ** (FunctionClauseError) no function clause matching in Access.get/3
Repo.all/1 should have raised Ecto.Query.CastError (as it does for ^{1, 2, 3} or [match: "x"]); instead the message construction of Ecto.QueryError crashes. Params held in a map rather than a keyword list do not reproduce. On Elixir 1.18 through 1.20, Macro.to_string({Foo, :cache, ["a", []]}) raises the same FunctionClauseError (reported to Elixir separately; this report does not depend on it).
Failure point: Inspect.Ecto.Query.expr/3, lib/ecto/query/inspect.ex#L260-L267, and the interpolated-value clause at L307-L318, both ending in Macro.to_string/1; Ecto.QueryError and Ecto.SubQueryError interpolate the inspected query at lib/ecto/exceptions.ex#L36 and L78, and Ecto.Query.Planner.cast_param/6 builds a QueryError for the CastError message at lib/ecto/query/planner.ex#L1153-L1161.
Reproduction: * Description, with the failure point at this release: https://github.com/grempe/ash-fuzz-repros#ectoinspect-query-crashes-on-spark-regex-type-param
Expected behavior
inspect/1 succeeds and Ecto.Query.CastError is raised normally.
Elixir version
Elixir 1.20.1 (compiled with Erlang/OTP 29), Erlang/OTP 29 (erts 17.0.2)
Database and Version
PostgreSQL 18.6
Ecto Versions
ecto 3.14.2, ecto_sql 3.14.0
Database Adapter and Versions (postgrex, myxql, etc)
postgrex 0.22.4
Current behavior
Found by an AI assistant working with a human who was fuzz-testing their own application; reduced to the following. Present on master at 24f914a (checked 2026-09-15).
No repo or database is needed for
inspect/1:The same tuple in an ordinary interpolated value reproduces it with a built-in type and no parameterized type:
The three-tuple is how Spark stores a
match:regex constraint ({Spark.Regex, :cache, [source, opts]}) and Ash's SQL layer copies a type's constraints into the Ecto type parameters, which is how it was hit; neither library is needed to reproduce.Repo.all/1should have raisedEcto.Query.CastError(as it does for^{1, 2, 3}or[match: "x"]); instead the message construction ofEcto.QueryErrorcrashes. Params held in a map rather than a keyword list do not reproduce. On Elixir 1.18 through 1.20,Macro.to_string({Foo, :cache, ["a", []]})raises the sameFunctionClauseError(reported to Elixir separately; this report does not depend on it).Failure point:
Inspect.Ecto.Query.expr/3, lib/ecto/query/inspect.ex#L260-L267, and the interpolated-value clause at L307-L318, both ending inMacro.to_string/1;Ecto.QueryErrorandEcto.SubQueryErrorinterpolate the inspected query at lib/ecto/exceptions.ex#L36 and L78, andEcto.Query.Planner.cast_param/6builds aQueryErrorfor theCastErrormessage at lib/ecto/query/planner.ex#L1153-L1161.Reproduction: * Description, with the failure point at this release: https://github.com/grempe/ash-fuzz-repros#ectoinspect-query-crashes-on-spark-regex-type-param
mix setup && mix test test/ecto/inspect_query_with_spark_regex_type_param_test.exsin https://github.com/grempe/ash-fuzz-reprosExpected behavior
inspect/1succeeds andEcto.Query.CastErroris raised normally.