Skip to content
Fran Gonzalez
← Back to blog
(updated Jul 16, 2026)·Clanker·4 min read

A gitignore re-include that never shipped broke my Tauri CI build

A Tauri resource glob hard-failed on CI with exit code 101 because a gitignore !KEEP re-include pointed at a file that was never committed, leaving the resources dir empty on fresh checkouts.

Some matmuls wrote this slop, sorry. My goal with this content is to document some work I (a real human bean) do while poking the Clanker, and try to learn something along the way.

A Tauri app built fine on my machine and failed in CI with exit code 101, a resource glob that matched nothing, and a directory the fresh checkout did not have. The cause was a .gitignore re-include rule pointing at a file that was never committed.

Symptom

The desktop app’s tauri.conf.json bundles every file under a resources directory into the final .app and .dmg:

// apps/desktop/src-tauri/tauri.conf.json
{
  "bundle": {
    "resources": ["resources/bin/**/*"]
  }
}

That directory holds binaries the app ships alongside itself: a deepb CLI and, on macOS, bundled ActivityWatch components. They are large and platform-specific, so they are not checked in. A mise task stages them at bundle time:

# prepare:bundle task in apps/desktop/mise.toml (excerpt)
RESOURCE_DIR="$APP_ROOT/src-tauri/resources/bin"
rm -rf "$RESOURCE_DIR"
mkdir -p "$RESOURCE_DIR"
cargo build --release -p deepblock-cli
cp "$TARGET_DIR/deepb" "$RESOURCE_DIR/deepb"

Because the binaries are ignored, the directory would otherwise be empty on a fresh clone. To keep it present, the .gitignore re-includes a KEEP sentinel:

# .gitignore
apps/desktop/src-tauri/resources/*
!apps/desktop/src-tauri/resources/bin/
apps/desktop/src-tauri/resources/bin/*
!apps/desktop/src-tauri/resources/bin/KEEP

The intent is clear: ignore the binaries, but track KEEP so the directory exists. The rust-workspace CI job runs cargo clippy --workspace, which compiles every crate including the Tauri one. On a fresh checkout it failed:

glob pattern resources/bin/**/* path not found or didn't match any files.
error: build failed, waiting for other jobs to finish...
##[error]Process completed with exit code 101.

Tauri’s build script resolves the resources globs at compile time. An empty or missing directory is a hard error, not a warning. The job exited with cargo’s 101. The macOS bundle job, which is the one that actually runs prepare:bundle and populates the directory, never got there.

Locally it always built, because the binaries were sitting in resources/bin/ from previous local bundle runs.

Root cause and fix

I assumed KEEP was tracked, because the .gitignore re-include rule was written for it. It was not:

$ git ls-files apps/desktop/src-tauri/resources/bin/
(empty)

A .gitignore !path re-include un-ignores a path. It does not create or commit the file. If nothing is ever git added there, the re-include matches nothing and the directory stays absent from the repo. The rule was a promise that was never kept.

To confirm the empty-directory hypothesis, I moved the local binaries aside, created only the sentinel, and compiled the desktop crate:

cd apps/desktop/src-tauri/resources/bin
mv aw-server-rust aw-watcher-afk aw-watcher-window deepb /tmp/backup
echo "placeholder for tauri resources glob (populated at bundle time)" > KEEP
cd -
cargo check -p deepblock-desktop
# Finished `dev` profile ... target(s) in 14.34s

The build succeeded with only KEEP present. That confirmed the glob needs the directory to exist and contain at least one file, and that any file satisfies it. The fix was committing the sentinel:

git add apps/desktop/src-tauri/resources/bin/KEEP

The .gitignore already allowed it through (git check-ignore apps/desktop/src-tauri/resources/bin/KEEP returns nothing), and the binaries stayed ignored. After the commit, cargo clippy --workspace passed on the fresh CI checkout.

Prevention

The re-include-without-commit was the real bug, but I would also question why a compile step depends on a directory whose contents only exist at bundle time. cargo clippy --workspace compiling the Tauri crate and evaluating resources globs couples the lint/test job to the bundling contract. A cleaner split would be either to make the build script tolerate an empty glob during non-bundle compiles, or to keep the test job from compiling the crate that carries bundle resources. The sentinel is a working fix; it is not the structural one.

References

This post was written with AI assistance.