From fc7bd30364299d90fcf41b79cef3b1e290ec52ef Mon Sep 17 00:00:00 2001 From: Steffen Beyer Date: Fri, 24 Apr 2026 11:20:39 +0200 Subject: [PATCH] fix: loadpaths before search_docs HTTP lookups in Mix projects When usage_rules.search_docs was invoked directly as a Mix task inside a project, the HTTPS request path could fail before the docs lookup ran with: ** (UndefinedFunctionError) function :ssl.versions/0 is undefined The failure site is in Mint's SSL transport setup, but the behavior pointed more strongly at the direct Mix task boot path than at a general Req/Mint/OTP SSL problem. The same logic worked via mix run, and forcing a compile also avoided the crash, which suggested the task needed proper project loadpath setup before starting Req. Use Mix loadpaths bootstrapping here instead of forcing mix compile. That keeps the HTTP client startup on the normal Mix project loadpath path while avoiding a regression where search_docs would fail early in projects that do not currently compile cleanly. This keeps the fix scoped to task startup and avoids papering over the issue by explicitly starting :ssl or requiring a full project compile before an online docs search can run. --- lib/mix/tasks/usage_rules.search_docs.ex | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/mix/tasks/usage_rules.search_docs.ex b/lib/mix/tasks/usage_rules.search_docs.ex index 0fe88fd..d112182 100644 --- a/lib/mix/tasks/usage_rules.search_docs.ex +++ b/lib/mix/tasks/usage_rules.search_docs.ex @@ -43,6 +43,10 @@ defmodule Mix.Tasks.UsageRules.SearchDocs do @impl true def run(args) do + if Mix.Project.get() do + loadpaths!() + end + {:ok, _} = Application.ensure_all_started(:req) {opts, args} = OptionParser.parse!(args, strict: @switches, aliases: @aliases) opts = Keyword.put(opts, :mix_project, !!Mix.Project.get()) @@ -434,6 +438,19 @@ defmodule Mix.Tasks.UsageRules.SearchDocs do false end + defp loadpaths! do + args = [ + "--no-elixir-version-check", + "--no-deps-check", + "--no-archives-check", + "--no-listeners" + ] + + Mix.Task.run("loadpaths", args) + Mix.Task.reenable("loadpaths") + Mix.Task.reenable("deps.loadpaths") + end + @spec raise_bad_args!() :: no_return() defp raise_bad_args! do Mix.raise("""