Skip to content

The app could not find its own Silero model once downloaded - #40

Merged
bojieli merged 2 commits into
mainfrom
fix/app-bundle-carries-its-own-resources
Sep 7, 2026
Merged

The app could not find its own Silero model once downloaded#40
bojieli merged 2 commits into
mainfrom
fix/app-bundle-carries-its-own-resources

Conversation

@bojieli

@bojieli bojieli commented Sep 7, 2026

Copy link
Copy Markdown
Owner

Every macOS release this project has cut dies on a fatalError the first time it records, on any machine that did not build it.

What happens

SwiftPM generates Bundle.module as Bundle.main.bundleURL plus 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 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 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 that ships 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

Confirmed it is the layout and not CI, by moving the local build directory aside: the locally built bundle then fails identically.

The fix

CoreResources replaces Bundle.module with a lookup over the layouts this project actually ships. It tests each candidate for the resource, not for a bundle that merely loads — the .xctest bundle 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 error SpeechActivity already had rather than killing the process.

So it 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 rather than 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. 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

bojieli and others added 2 commits September 7, 2026 12:48
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>
@bojieli
bojieli merged commit d2db0ee into main Sep 7, 2026
13 checks passed
@bojieli
bojieli deleted the fix/app-bundle-carries-its-own-resources branch September 7, 2026 05:14
@bojieli bojieli mentioned this pull request Sep 7, 2026
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