From f29b0f35bb2e04b3e47e7485660f585f1f3b1607 Mon Sep 17 00:00:00 2001 From: Dominic Letz Date: Sun, 9 Aug 2026 02:16:15 +0800 Subject: [PATCH] extra_applications(:host): guard wx_app_on_disk?/0 against nil Enum.find/2 returns nil when no matching directory is found, but the with clause used an unbound pattern that silently matched nil and let the body run with wx_dir = nil, crashing Path.join/1 with: ** (FunctionClauseError) no function clause matching in IO.chardata_to_string/1 (called with nil) (elixir 1.16.3) lib/path.ex:672: Path.do_join/3 lib/desktop/mix.exs: Desktop.MixProject.wx_app_on_disk?/0 Reproducible on any OTP build configured --without-wx (e.g. the elixir-desktop/ddrive macOS installer CI): the OTP root's lib/ directory has no wx-* entry, Enum.find returns nil, and the probe crashes instead of returning false. Add an is_binary(wx_dir) guard so the with chain falls through to the existing `else _ -> false` clause on a no-wx host, and document the pitfall in the comment block above extra_applications/1. Fixes the regression introduced in #82 and unblocks downstream PRs that bump the desktop dep to include the fs probe. Co-authored-by: Cursor --- mix.exs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mix.exs b/mix.exs index fe71444..f8b6bef 100644 --- a/mix.exs +++ b/mix.exs @@ -90,7 +90,11 @@ defmodule Desktop.MixProject do # is evaluated under `mix deps.compile` — the previous deps' `compile.all` # prunes the code path and forgets the apps it never listed. Check the # filesystem directly instead, mirroring what `desktop_wx_stub.exs` - # already does via `wx_headers_resolvable?/0`. + # already does via `wx_headers_resolvable?/0`. The `with` clause guards + # `wx_dir` against `nil` because `Enum.find/2` returns `nil` when no + # `wx-*` directory exists under the OTP root (the case on `--without-wx` + # builds), and an unbound pattern would otherwise let the body run with + # `wx_dir = nil` and crash `Path.join/1`. if wx_app_on_disk?() do [:wx] else @@ -106,7 +110,8 @@ defmodule Desktop.MixProject do root = List.to_string(:code.root_dir()) with {:ok, entries} <- File.ls(Path.join(root, "lib")), - wx_dir <- Enum.find(entries, &String.starts_with?(&1, "wx-")) do + wx_dir when is_binary(wx_dir) <- + Enum.find(entries, &String.starts_with?(&1, "wx-")) do File.exists?(Path.join([root, "lib", wx_dir, "include", "wx.hrl"])) else _ -> false