macOS Deployment Pitfalls
Critical macOS-specific deployment issues that cause subtle, hard-to-debug failures
macOS Deployment Pitfalls
This page documents the single most frustrating debugging issue in Tauri macOS deployment. If you spend hours wondering why your latest code changes are not taking effect after a build, this is almost certainly why.
The #1 Pitfall: cp -rf is BROKEN for .app Bundles
⚠️ Warning
Never use cp -rf to overwrite an existing .app bundle. Always remove the old .app first, then copy.
# WRONG - binary inside stays stale
cp -rf target/release/bundle/macos/MyApp.app /Applications/
# CORRECT - remove first, then copy
rm -rf /Applications/MyApp.app
cp -r target/release/bundle/macos/MyApp.app /Applications/ Why This Happens
A .app bundle is a directory structure:
MyApp.app/
Contents/
MacOS/
MyApp <-- The actual binary
Resources/
...
Info.plist
When you cp -rf a new .app over an existing one, macOS’s cp command behaves unexpectedly:
- It copies new and changed files into the existing directory
- But the binary inside
Contents/MacOS/may not be replaced if it is currently in use, cached by the kernel, or has certain file flags - The result: the
.appbundle looks new (newInfo.plist, new resources), but the actual executable is the old version
You end up running old code with new metadata, which produces incredibly confusing behavior. Your changes are not showing up, your logs say the right version, but the behavior is wrong.
The Correct Procedure
Always follow this sequence:
# 1. Kill the running app (if any)
killall MyApp 2>/dev/null || true
# 2. Wait briefly for process to exit
sleep 1
# 3. Remove the old bundle completely
rm -rf /Applications/MyApp.app
# 4. Copy the fresh bundle
cp -r target/release/bundle/macos/MyApp.app /Applications/
# 5. Clear quarantine
xattr -cr /Applications/MyApp.app
Verify the Binary is Fresh
After installing, verify that the binary timestamp matches your build:
# Check when the binary was last modified
stat -f "%Sm" /Applications/MyApp.app/Contents/MacOS/MyApp
# Compare with the source
stat -f "%Sm" target/release/bundle/macos/MyApp.app/Contents/MacOS/MyApp
Both timestamps should be identical (or within seconds of each other). If the /Applications/ binary has an older timestamp, the copy did not work correctly.
💡 Tip
Create a shell alias or script for the install procedure so you never accidentally use cp -rf:
# ~/.zshrc
install-tauri() {
local app_name="${1:?Usage: install-tauri AppName}"
killall "$app_name" 2>/dev/null || true
sleep 1
rm -rf "/Applications/${app_name}.app"
cp -r "target/release/bundle/macos/${app_name}.app" /Applications/
xattr -cr "/Applications/${app_name}.app"
echo "Installed ${app_name}.app"
} Other macOS Issues
App Translocation
macOS may “translocate” apps that are opened for the first time from certain locations (like the Downloads folder). Translocation copies the app to a random temporary directory and runs it from there, which breaks relative paths.
Clearing the quarantine attribute with xattr -cr prevents this:
xattr -cr /Applications/MyApp.app
Gatekeeper Warnings
Unsigned apps trigger Gatekeeper warnings. For development, you can bypass this by:
- Right-clicking the app and selecting “Open” (instead of double-clicking)
- Or clearing extended attributes:
xattr -cr /Applications/MyApp.app
For distribution, you will need to sign and notarize the app through Apple’s developer program.
Binary Code Signature
Even in development, if you modify the binary inside the .app bundle after it was created by Tauri, the code signature becomes invalid. macOS may refuse to run the app or show a “damaged” error.
If you see this after a correct install, try:
codesign --remove-signature /Applications/MyApp.app
xattr -cr /Applications/MyApp.app
Summary Checklist
Before reporting “my changes are not showing up”:
- Did you
rm -rfthe old.appbefore copying? (Notcp -rf) - Did you
killallthe running app first? - Do the binary timestamps match between source and installed?
- Did you clear quarantine with
xattr -cr? - Did you verify the frontend assets are actually embedded? (See Cargo Cache)