Skip to content

fix(macos): guard Sparkle updater against empty SUFeedURL in debug builds#30021

Closed
lailoo wants to merge 1 commit intoopenclaw:mainfrom
lailoo:fix/hide-updater-debug-build-29926
Closed

fix(macos): guard Sparkle updater against empty SUFeedURL in debug builds#30021
lailoo wants to merge 1 commit intoopenclaw:mainfrom
lailoo:fix/hide-updater-debug-build-29926

Conversation

@lailoo
Copy link

@lailoo lailoo commented Feb 28, 2026

Summary

Prevent the Sparkle "Appcast feed is empty" error dialog on macOS debug builds by checking SUFeedURL before initializing the Sparkle updater controller.

Problem

When the macOS app is packaged with a .debug bundle ID, scripts/package-mac-app.sh intentionally blanks SUFeedURL. However, makeUpdaterController() only checked for .app bundle extension and Developer ID signing — not whether the feed URL was actually set. If a debug-signed build passed the signing check, Sparkle would be initialized with an empty feed URL, causing the error:

Update Error! Appcast feed () after trimming it of quotes is empty for OpenClaw!

Closes #29926

Root cause

makeUpdaterController() in MenuBar.swift:458 has a guard that only checks isBundledApp and isDeveloperIDSigned(). When both pass on a debug build, SparkleUpdaterController is initialized with an empty SUFeedURL, triggering the Sparkle error dialog.

Changes

  • apps/macos/Sources/OpenClaw/MenuBar.swift — Added a SUFeedURL emptiness check in makeUpdaterController(): returns DisabledUpdaterController when the feed URL is missing or empty, which causes the About screen to show "Updates unavailable in this build." instead of triggering a Sparkle error.
  • apps/macos/Tests/OpenClawIPCTests/UpdaterControllerTests.swift — Added regression tests verifying DisabledUpdaterController reports isAvailable = false, checkForUpdates is a no-op, and AboutSettings renders correctly with a disabled updater.
  • src/gateway/server-cron.ts — Fixed pre-existing type error: agentEntry has type false | AgentConfig due to && short-circuit; replaced agentEntry?.heartbeat with agentEntry && agentEntry.heartbeat to satisfy TypeScript.

Reproduction & verification

Bug confirmed (source analysis on main):

  • makeUpdaterController() at MenuBar.swift:461 only guards on .app extension + Developer ID signing
  • package-mac-app.sh:28-30 blanks SUFeedURL for .debug bundle IDs
  • No check for empty feed URL before Sparkle initialization

Fix verified:

  • Swift tests (UpdaterControllerTests) 3/3 passed on fix branch:
    • disabledUpdaterReportsUnavailable
    • disabledUpdaterCheckIsNoOp
    • aboutSettingsShowsUnavailableForDisabledUpdater
  • tsgo type check passes (server-cron.ts error resolved)

Test plan

  • New test: UpdaterControllerTests.swift — 3 regression tests
  • Swift tests pass on fix branch
  • CI type error (server-cron.ts) fixed in separate commit

Effect on User Experience

Before: Debug builds show a confusing "Appcast feed is empty" Sparkle error dialog when clicking "Check for Updates" in About.

After: Debug builds show a clean "Updates unavailable in this build." message in the About screen, and the update toggle/button are hidden.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 28, 2026

Greptile Summary

This PR fixes a macOS-specific bug where debug builds displayed a confusing "Appcast feed is empty" error dialog when checking for updates. The fix adds a guard check for empty SUFeedURL before initializing the Sparkle updater controller.

Key changes:

  • apps/macos/Sources/OpenClaw/MenuBar.swift: Added !feedURL.isEmpty check in makeUpdaterController() to return DisabledUpdaterController when SUFeedURL is blank (as it is for debug builds)
  • apps/macos/Tests/OpenClawIPCTests/UpdaterControllerTests.swift: Added regression tests verifying DisabledUpdaterController reports unavailable status and doesn't trigger Sparkle dialogs
  • CHANGELOG.md: Documented the fix

The implementation correctly addresses the root cause: scripts/package-mac-app.sh intentionally sets SPARKLE_FEED_URL="" for .debug bundle IDs, but the previous code only checked for .app extension and Developer ID signing, allowing Sparkle to initialize with an empty feed URL.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The fix is minimal, well-targeted, and addresses a specific debug-build issue without affecting production. The guard check order is optimal (cheap checks before expensive code signature verification), tests verify the expected behavior, and the change cannot introduce regressions in production builds since it only affects cases where SUFeedURL is empty.
  • No files require special attention

Last reviewed commit: b54afc7

@openclaw-barnacle openclaw-barnacle bot added the gateway Gateway runtime label Feb 28, 2026
Copy link

@nikolasdehor nikolasdehor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Sparkle SUFeedURL guard fix is clean and correct. However, the second commit (chore: fix server-cron.ts heartbeat type error) conflicts with PRs #30048 and #30010 which fix the exact same line differently. #30048's ternary approach is the cleanest because it eliminates false from the union type at the source. Recommend dropping the server-cron.ts commit from this PR and letting #30048 handle it — the Sparkle fix on its own is an easy APPROVE.

@openclaw-barnacle openclaw-barnacle bot removed the gateway Gateway runtime label Feb 28, 2026
@lailoo
Copy link
Author

lailoo commented Feb 28, 2026

Thanks @nikolasdehor for the quick and thorough review! Dropped the server-cron.ts commit — letting #30048 handle that fix. This PR now only contains the Sparkle empty SUFeedURL guard.

@openclaw-barnacle
Copy link

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle bot added the stale Marked as stale due to inactivity label Mar 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: macos App: macos size: XS stale Marked as stale due to inactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] macOS updater error: Appcast feed is empty in About → Check for Updates (2026.2.26)

3 participants