Skip to content

fix: run gettext after dialyzer so they stop sharing _build - #91

Merged
jimsynz merged 1 commit into
mainfrom
fix/keep-gettext-extraction-out-of-dialyzers-way
Aug 27, 2026
Merged

fix: run gettext after dialyzer so they stop sharing _build#91
jimsynz merged 1 commit into
mainfrom
fix/keep-gettext-extraction-out-of-dialyzers-way

Conversation

@jimsynz

@jimsynz jimsynz commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

What

Make the gettext tool in .check.exs depend on dialyzer as well as
ex_unit, so mix gettext.extract no longer runs alongside mix dialyzer.

Why

mix gettext.extract --check-up-to-date re-expands the gettext macros by
force-recompiling the project (mix compile --force-elixir +
mix compile.elixir --force). A forced recompile empties
_build/dev/lib/bb_example_so101/ebin and .../consolidated for a second or two
before refilling them, and ex_check was running that tool in parallel with
mix dialyzer.

Elixir's build lock serialises the two compiles, but dialyzer reads beams after
it releases the lock — first when checking the PLT, then when it globs the ebin
to build its file list. If the wipe lands in either phase, dialyzer fails:

:dialyzer.run error: File not found:
  .../_build/dev/lib/bb_example_so101/consolidated/Elixir.Collectable.beam
  files: [],
:dialyzer.run error: Analysis failed with error:
No .beam files to analyze (no --src specified?)
Halting VM with exit status 1

That is what failed the bb_example_so101 job in bb's Test Subprojects
workflow on the v0.30.1 tag push (run 32619948357), and it is the same failure
tracked in beam-bots/bb#245 for bb_example_wx200. Those two are the only
packages in the ecosystem with both gettext and dialyxir, which is why only
they are affected. bb's workflow deletes _build/*/*.plt.hash before
mix check, forcing dialyxir's full PLT re-check and widening the exposure from
sub-second to roughly twenty seconds — hence the failures show up there and
essentially never here.

Verification

The mechanism was diagnosed and reproduced in bb_example_wx200
(beam-bots/bb_example_wx200#97), where mix gettext.extract overlapping
mix dialyzer reproduces the error above byte for byte, and the same one-line
change moves the forced recompile to after dialyzer finishes. This repo has an
identical tool set and .check.exs; the change here has not been run through a
local mix check of its own.

The deps: [:ex_unit, :dialyzer] restates :ex_unit because ex_check replaces
the option rather than merging it.

`mix gettext.extract --check-up-to-date` force-recompiles the project so the
gettext macros re-expand. A forced recompile empties
`_build/dev/lib/bb_example_so101/ebin` and `.../consolidated` for a second or
two before refilling them, and `ex_check` was running that tool alongside
`mix dialyzer`.

Elixir's build lock serialises the two compiles, but not dialyzer's beam
reads, which happen after it releases the lock. When the wipe lands in that
phase, dialyzer either fails to read a consolidated protocol beam or enumerates
an empty ebin and halts with "No .beam files to analyze".

Making `gettext` depend on `dialyzer` moves the forced recompile to the end of
the run, when nothing else is reading the build directory.
@jimsynz
jimsynz merged commit f2c5f03 into main Aug 27, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant