Skip to content

Cannot grant BetterDiscord Installer v2 permission to modify Discord on macOS #424

Open

Description

@12joan

Describe the bug
I'm unable to find any way of granting BetterDiscord permission to modify Discord on macOS unless I manually select Discord's Resources directory.

To Reproduce
Steps to reproduce the behaviour:

  1. Download v2.0.0 from the releases page on GitHub
  2. Unzip and remove the quarantine flag using xattr -d com.apple.quarantine <path to app>
  3. Open BetterDiscord and attempt to install
  4. macOS reports that BetterDiscord was prevented from modifying apps on your Mac
  5. Click the Allow button and enable the App Management permission for BetterDiscord
  6. Relaunch BetterDiscord and try again
  7. During the installation attempt, the App Management permission switch can be seen turning itself off, and we return to step 4 to loop indefinitely

I've also tried granting BetterDiscord full disk access, which didn't work either, although that permission remains enabled unlike App Management.

Screen recording

recording.mp4

System Information:

  • OS: macOS 26.5.2 (25F84)
  • Discord Version: Stable (0.0.409)

Additional context
For some reason, the problem seems to go away if I use the browse button to select /Applications/Discord.app/Contents/Resources, even though that's the default path. The first time I tried this, nothing seemed to happen (Discord relaunched but seemingly without BetterDiscord enabled), but the second time, Discord relaunched and asked me to sign back into my account (which I've never seen before).

After signing in, BetterDiscord appeared to be enabled (I saw my custom theme and the BetterDiscord popup), but Discord now crashes consistently (the "Something crashed your Discord Client" message) whenever I try to unmute my microphone, even though I've got no plugins enabled. Pressing the try again button produces a popup with the following error message:

Uncaught exception:
TypeError: Object has been destroyed
at WebContents.<anonymous> (/Users/joe/Library/Application Support/discord/app-0.0.409/modules/discord_desktop_core-1/discord_desktop_core/core.asar/bundle.js:1:118273)
at WebContents.emit (node:events:521:24)
at emitter.emit (/Applications/Discord.app/Contents/Resources/betterdiscord.app.asar/bundle.js:505:106132)

Since BetterDiscord's uninstall feature also seems to be broken (it says it can't stop Discord even when Discord isn't running), I deleted Discord entirely, redownloaded it from the official page, and then reinstalled BetterDiscord using the v1.3.0 installer. Everything is now working fine.

Activity

  1. FearNaBoinne commented on Aug 29, 2026

    @FearNaBoinne

    The workaround (Settings -> Privacy & Security -> Full Disk; then click the + at the bottom and add the installer) worked for me...

    (Also, 2.0 did NOT correctly inject in PTB, so I tried 1.3, which popped up the App Management request. I allowed it and re-ran the injection. The injection worked and App Management remains enabled here now!)

  2. zerebos commented on Aug 29, 2026

    @zerebos
    Member

    Thanks for the update, I'll have to continue to look into this... I tested it on my two macs and didn't run into this. I'll have to grab another so I can try to recreate the issue.

  3. xITmasterx commented on Aug 30, 2026

    @xITmasterx

    I have encountered the same issue with the same problems.

  4. OneshotFire commented on Aug 30, 2026

    @OneshotFire

    Root cause found, and it's reproducible from the released artifact alone — nothing to do with any individual Mac, which is why it doesn't reproduce on a locally-built copy.

    The shipped .app is not signed as a bundle. Downloading BetterDiscord-Installer-Mac.zip from releases/latest and inspecting it:

    $ codesign -dvvv "BetterDiscord Installer.app"
    Identifier=a.out
    CodeDirectory v=20400 flags=0x20002(adhoc,linker-signed)
    Signature=adhoc
    Info.plist=not bound
    Sealed Resources=none
    
    $ codesign --verify --strict "BetterDiscord Installer.app"
    BetterDiscord Installer.app: code object is not signed at all
    
    $ spctl -a -vvv "BetterDiscord Installer.app"
    rejected
    source=no usable signature
    

    Identifier=a.out is the Go linker's default ad-hoc signature on the bare binary. Info.plist=not bound and Sealed Resources=none mean the bundle itself was never signed.

    Why that causes the App Management loop specifically: macOS keys kTCCServiceSystemPolicyAppBundles approvals to a code signature it can re-validate on each launch. With no sealed bundle and an identifier of a.out, validation fails, so TCC discards the grant — the user approves, it appears to work, and it's gone by the next launch. That is exactly the "I gave permission but it resets" report in this thread and in #390.

    This also explains why v1.3 worked for @FearNaBoinne while 2.0 didn't: electron-builder signed the bundle, and the current GoReleaser pipeline doesn't. .goreleaser.yaml assembles the .app purely by file placement inside the archive (universal_binaries.name_template puts the binary at the bundle path, then archives.files adds Info.plist and the icon), so there is no point at which the assembled bundle is handed to codesign.

    Confirming the fix locally — re-signing the installed copy makes the grant stick permanently:

    codesign --force --deep --sign - \
      --identifier app.betterdiscord.installer \
      "/Applications/BetterDiscord Installer.app"
    tccutil reset SystemPolicyAppBundles app.betterdiscord.installer

    After that the App Management approval persisted across relaunches and the injection worked. This is a workaround others in this thread can use today.

    For the real fix, the bundle needs signing in the release pipeline. Ad-hoc signing is enough to make TCC grants persist and needs no Apple account; a Developer ID + notarization would additionally fix Gatekeeper and keep the grant across updates (ad-hoc changes the cdhash each release, so approval is re-requested after each update). Happy to open a PR with the pipeline change if useful.

  5. OneshotFire commented on Aug 30, 2026

    @OneshotFire

    Had the same issue, let claude fix it for me with the write up above.

  6. zerebos commented on Aug 30, 2026

    @zerebos
    Member

    Thanks for looking into this @OneshotFire (and Claude)! The core of this seems to check out.

    The shipped .app is genuinely not signed as a bundle. The zip has no Contents/_CodeSignature/ at all, and the arm64 slice carries the Go linker's default ad-hoc signature with Identifier=a.out, which contradicts our bundle's own CFBundleIdentifier (app.betterdiscord.installer). The x86_64 slice has no signature whatsoever, so Intel builds are entirely bare.

    Quick correction on your reasoning though: v1.3.0 was not signed by electron-builder. I pulled the release and there was no _CodeSignature anywhere, and the binary is a thin x86_64 ach-O with no LC_CODE_SIGNATURE at all. It was technically less signed than v2.0.0.

    That inverts your explanation a bit but the conclusion is still essentially correct. The real contrast is "unsigned" vs. "signed but unsealed," and the second is worse: with a signature present, macOS records a code requirement for the App Management grant, then can't re-validate it against an unsealed bundle, so it drops the grant. That matches the toggle visibly switching itself off mid-attempt, and it lines up with @FearNaBoinne's report that v1.3 kept the permission. I also checked that the merged universal binary's signature isn't corrupt and all 2301 code page hashes verify just fine so this is purely a bundle-sealing problem.

    It still doesn't explain how it didn't reproduce on either of my Macs because a locally-built copy should be in the same state as the release. So there's probably some more poking around to do on my own setups.

    I'm working on a pipeline change that ad-hoc signs the bundle. Some caveats with this solution:

    • It does not fix Gatekeeper. The app is still unnotarized, so the right-click-Open / xattr steps stay.

    • Ad-hoc signatures change every release, so macOS will re-ask for App Management after each update. Thankfully installer updates are very rare.

    • If the toggle shows as already enabled while injection still fails, macOS is probably holding a stale entry; clear it once and re-grant:

      tccutil reset SystemPolicyAppBundles app.betterdiscord.installer

    Also it's probably worth noting why v1.3 didn't have this problem... It was Intel-only, and x86_64 binaries can ship completely unsigned. Apple Silicon refuses to execute unsigned arm64 code, so v2.0's native arm64 slice had to carry a signature. In our case we had the Go linker's ad-hoc one. Adding Apple Silicon support is what forced a signature into existence and exposed the fact that the bundle around it was never sealed.

    If anyone still hitting this can try @OneshotFire's local workaround and report whether the grant survives a few relaunches, that would confirm the mechanism before I commit and push this out.

  7. spdys commented on Aug 31, 2026

    @spdys

    even after giving it full disk access AND trying the above claude fix, I get the same error but instead of "operation not permitted" i get "permission denied" at the exact same step. even tried with bdcli and got the same "operation not permitted" error. i have to keep using the macos shortcut, it's the only thing that works atm.

  8. zerebos commented on Aug 31, 2026

    @zerebos
    Member

    Can you provide the full log and screenshots?

  9. Ant-V commented on Sep 6, 2026

    @Ant-V

    I also have the same issue, but running MacOS 27 (beta 8, 26A5425a)
    I thought it was an issue with a newer permissions check and it reseting due to the executable being modified mid-run (downloading the .asar) or something, but I see @12joan is on 26.5.2...

  10. colineberly commented on Sep 6, 2026

    @colineberly

    Had the same issue, @OneshotFire's solution worked great. I'll see how relaunches go.

  11. korboybeats commented on Sep 12, 2026

    @korboybeats

    What worked for me:

    After applying the codesign + tccutil workaround above, the error changed from:

    operation not permitted
    

    to:

    permission denied
    

    The remaining issue was that my user account could not write to Discord’s Resources directory.

    I fixed it with:

    sudo chown -R "$USER":staff "/Applications/Discord.app/Contents/Resources"
    sudo chmod -R u+rwX "/Applications/Discord.app/Contents/Resources"

    Then verified it was writable with:

    touch "/Applications/Discord.app/Contents/Resources/test-write" && \
    rm "/Applications/Discord.app/Contents/Resources/test-write"

    After that, BetterDiscord installed successfully.

    So for me there were two separate issues: the Installer v2 signing/App Management issue, then the permissions on Discord’s Resources directory.

  12. RKursatV commented on Oct 23, 2026

    @RKursatV

    Another workaround that sidesteps the App Management / Resources permission problem entirely (no sudo, no TCC grant, nothing written to /Applications): inject the way the v1.x installer did, via Discord's per-user core module.

    Tested on macOS 26.6.2, Discord Stable 0.0.419, using the betterdiscord.asar the v2 installer had already downloaded before failing.

    1. Fully quit Discord (Cmd+Q).
    2. Patch the core module's index.js (adjust the version folder to yours):
    CORE="$HOME/Library/Application Support/discord/app-0.0.419/modules/discord_desktop_core-1/discord_desktop_core"
    cp "$CORE/index.js" "$CORE/index.js.orig"
    printf 'require("%s");\nmodule.exports = require("./core.asar");\n' \
      "$HOME/Library/Application Support/BetterDiscord/data/betterdiscord.asar" > "$CORE/index.js"
    1. Start Discord. BetterDiscord loads normally ([BetterDiscord] [Startup] … in ~/Library/Application Support/discord/logs/renderer_js.log).

    If BetterDiscord/data/betterdiscord.asar doesn't exist yet, grab betterdiscord.asar from the latest BetterDiscord release and put it there first.

    Caveat: a Discord update replaces the app-0.0.x folder, so this has to be redone after each Discord update. To undo, restore index.js.orig.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions