The app could not find its own Silero model once downloaded - #40
Merged
Conversation
Every macOS release this project has cut dies on a fatalError the first time it
records, on any machine that did not build it.
SwiftPM generates Bundle.module as `Bundle.main.bundleURL` + the sibling bundle
name, falling back to an absolute path inside the build tree. For an app,
bundleURL is the .app itself — and a resource cannot live at the .app root,
because everything signed sits under Contents/. So `make app` puts it in
Contents/Resources, the generated lookup never matched, and what actually
resolved it every time was the fallback: /Users/boj/DoNotType/.build/... locally,
/Users/runner/work/DoNotType/... in CI. Both exist on the machine that compiled
the binary and nowhere else. The Makefile asserted the opposite in a comment,
which is why nobody went looking.
It is invisible to every test we had. The build machine is the test machine, so
the fallback is always present; the launch check passes because the app starts
fine and only dies when SpeechActivity loads the model, which is every recording
and every `dnt transcribe`.
Found by installing 0.6.2 through Homebrew and transcribing one file with the
`dnt` inside the bundle:
Fatal error: could not load resource bundle: from
/Applications/DoNotType.app/DoNotType_DoNotTypeCore.bundle or
/Users/runner/work/DoNotType/DoNotType/.build/.../DoNotType_DoNotTypeCore.bundle
CoreResources replaces Bundle.module with a lookup that tries the layouts this
project actually ships, checking for the resource rather than for a bundle that
merely loads — the .xctest bundle loads and does not carry it, which caught the
first version of the list. It returns nil instead of trapping, so a build that
genuinely lacks the model degrades to the error SpeechActivity already had
rather than killing the process.
Two things so this cannot come back quietly:
- `dnt doctor` reports the model, beside the opus encoder. Whether it resolves
is a property of how the binary was packaged, not of the code, so there has to
be something on this side of the network to ask.
- scripts/macos-bundle-selfcontained.sh hides every build-directory resource
bundle and makes the .app answer from its own contents, run in CI after the
launch check. Verified both ways: it fails against the 0.6.2 bundle and passes
against this one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
mapfile is a bash 4 builtin. macOS ships bash 3.2 at /bin/bash, so the check passed on a developer machine with Homebrew bash on PATH and failed on the runner — the same shape of mistake the check itself exists to catch, which is that 'works where it was written' is not evidence. Verified under /bin/bash 3.2 both ways: passes the fixed bundle, fails the 0.6.2 one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every macOS release this project has cut dies on a
fatalErrorthe first time it records, on any machine that did not build it.What happens
SwiftPM generates
Bundle.moduleasBundle.main.bundleURLplus the sibling bundle name, falling back to an absolute path inside the build tree. For an app,bundleURLis the.appitself — and a resource cannot live at the.approot, because everything signed sits underContents/. Somake appputs it inContents/Resources, the generated lookup never matched, and what resolved it every time was the fallback:/Users/boj/DoNotType/.build/…locally,/Users/runner/work/DoNotType/…in CI. Both exist on the machine that compiled the binary and nowhere else.The Makefile asserted the opposite in a comment, which is why nobody went looking. That comment is corrected here.
Why nothing caught it
The build machine is the test machine, so the fallback is always present. The launch check passes because the app starts fine — it only dies when
SpeechActivityloads the model, which is every recording and everydnt transcribe.Found by installing 0.6.2 through Homebrew and transcribing one file with the
dntthat ships inside the bundle:Confirmed it is the layout and not CI, by moving the local build directory aside: the locally built bundle then fails identically.
The fix
CoreResourcesreplacesBundle.modulewith a lookup over the layouts this project actually ships. It tests each candidate for the resource, not for a bundle that merely loads — the.xctestbundle loads and does not carry it, which caught the first version of the list and broke 23 tests until fixed. It returns nil instead of trapping, so a build genuinely missing the model degrades to the errorSpeechActivityalready had rather than killing the process.So it cannot come back quietly
dnt doctorreports the model, beside the opus encoder. Whether it resolves is a property of how the binary was packaged rather than of the code, so there has to be something on this side of the network to ask.scripts/macos-bundle-selfcontained.shhides every build-directory resource bundle and makes the.appanswer from its own contents. Runs in CI after the launch check. Verified in both directions: it fails against the 0.6.2 bundle and passes against this one.Full suite: 604 tests, 0 failures.
Released versions are affected
v0.6.0, v0.6.1 and v0.6.2 all carry this. Anyone who downloaded one has an app that crashes on its first recording. Worth deciding what to do about those release pages separately from this fix.
🤖 Generated with Claude Code