Skip to content

Menubar icon never renders on macOS 26.5.1 (25F80) with 0.9.19 — #146 recurrence, no RenderBox fault #868

Closed

Description

@twodxme

Summary

Menubar icon never renders on macOS 26.5.1 (Build 25F80) with CodeBurnMenubar 0.9.19. The app launches and keeps running, the CLI contract is healthy, the status-item scene is created — but nothing ever draws. This looks like a recurrence of #146 on a newer macOS build, with one notable difference from the related CodexBar report (steipete/CodexBar#805): no RenderBox precondition failure appears in the log, so the #147 fix path ("start as .regular, activate, simple image first") may not cover whatever changed in 26.5.x.

Environment

  • CodeBurnMenubar: 0.9.19 (fresh codeburn menubar --force install; version verified via PlistBuddy)
  • macOS: 26.5.1 / Build 25F80
  • Hardware: MacBook Pro (M3 Max)
  • Install location: /Users/tim/Applications/CodeBurnMenubar.app
  • No menubar manager (no Bartender/Ice/HiddenBar); ample free menubar space (notch ruled out)

Actual behavior

  • Process launches and stays alive; no crash.
  • No menu bar icon, ever.
  • Light/Dark appearance toggle has no effect (rules out the appearance-specific render failure seen in CodexBar#805).

CLI contract is healthy

$ time codeburn status --format menubar-json | head -c 400
{"generated":"2026-08-01T05:03:14.207Z","current":{"label":"Today (2026-07-31)","cost":0,...}
codeburn status --format menubar-json  0.56s user 0.18s system 123% cpu 0.606 total

Diagnostics (unified log)

Status-item scene is created:

CodeBurnMenubar: (AppKit) [com.apple.AppKit:StatusBar] 0 create scene 5DAF1172-A4D9-4468-A834-365D847350B3
CodeBurnMenubar: (BoardServices) [com.apple.BoardServices:XPCErrors] [C:1] Alloc com.apple.controlcenter.statusitems

Control Center scene requests complete, but the NSStatusItemView aux scene loops on reconnect:

[com.apple.FrontBoard:Common] Requesting scene <FBSScene: ...; com.apple.controlcenter:3B7E320E-...-Aux[1]-NSStatusItemView> from com.apple.controlcenter.statusitems
[com.apple.FrontBoard:SceneClient] [...-Aux[1]-NSStatusItemView] Sending action(s) in update: NSSceneFenceAction
[com.apple.FrontBoard:SceneClient] [...-Aux[1]-NSStatusItemView] Dropping transition context because the scene is reconnecting
(repeats several times)
[com.apple.FrontBoard:Common] Request for <FBSScene: ...> complete!

~5 seconds after launch, AppKit marks the app auto-terminable, consistent with "no visible UI ever materialized":

[com.apple.AppKit:AutomaticTermination] void _updateToReflectAutomaticTerminationState(void) Setting _kLSApplicationWouldBeTerminatedByTALKey=1

Grepping --info --debug logs for statusbar|renderbox|precondition|isVisible shows no RenderBox fault and no StatusBar state dump with isVisible=0 — unlike the CodexBar case on 26.4.x.

Already ruled out

  • Notch / menubar overflow (ample space; external display checked)
  • Persisted hidden state (NSStatusItem Visible Item-0 key absent from prefs)
  • Stale saved position (NSStatusItem Preferred Position Item-0 = 5694 was present; deleted — no change)
  • Full pref reset: defaults delete org.agentseal.codeburn-menubar + killall cfprefsd + relaunch
  • killall ControlCenter (scene re-request) — no change
  • Quarantine (cleared by the installer; app launches fine)
  • Stale build (0.9.19 is the newest mac release; the Fix NSStatusItem not rendering on macOS Tahoe (26.x) #147 fix shipped in 0.9.0)
  • Node/CLI health (valid menubar-json in 0.6s, Node 22.13+)

Possibly useful cross-reference

steipete/CodexBar#805 hit the invisible-status-item failure on 26.4.x even after their first timing fix, and needed a second rendering rework (steipete/CodexBar#849, "restore menu bar icon on macOS 26.4") that moved icon rendering off the SwiftUI compositing/RenderBox path. Given 26.5.1 shows a scene-reconnect loop with no RenderBox fault, whatever Control Center changed may now require an equivalent second-round fix here.

Happy to provide fuller log show output or test a patched build.

Activity

  1. ozymandiashh commented on Aug 2, 2026

    @ozymandiashh
    Collaborator

    Two things from digging through this, one that narrows the search and one that widens it.

    The RenderBox/SwiftUI path does not apply here. CodeBurn's status item is drawn with plain AppKit, never through SwiftUI compositing, so the CodexBar #849 rework has no analogue in this codebase. There is no MenuBarExtra anywhere in mac/Sources (zero hits), and the button content is an NSImage plus an NSAttributedString:

    • CodeBurnApp.swift:911 statusItem = NSStatusBar.system.statusItem(withLength: statusItemWidth)
    • CodeBurnApp.swift:921 button.image = flame (SF Symbol, isTemplate = true)
    • CodeBurnApp.swift:1052 button.attributedTitle = composed

    NSHostingController appears only at :1116 (popover content) and :1261 (Settings window), never on the status-item button. That is consistent with your observation that no RenderBox fault shows up in the log, and it means the absence of that fault is expected here rather than a clue.

    There is a different, concrete regression candidate: the #146/#147 workaround was reverted and never revisited.

    2268a8a (2026-04-24, PR #147, fixes #146) introduced exactly the ordering your symptom points at:

    // On macOS Tahoe (26.x), accessory apps may fail to render their status item
    // as a regular app and switching to accessory after setup works around this.
    NSApp.setActivationPolicy(.regular)
    NSApp.activate(ignoringOtherApps: true)
    // ... setupStatusItem() ...
    // Switch to accessory policy after status item is set up to hide from Dock
    NSApp.setActivationPolicy(.accessory)

    Eight days later 85b5728 / db99319 (2026-05-02, "Fix menubar ghost status item on macOS Tahoe") removed that dance and moved the policy call into applicationWillFinishLaunching, with the opposite rationale:

    // Set accessory policy before the app's focus chain forms. On macOS Tahoe
    // (26.x), setting it after didFinishLaunching causes ghost status items
    NSApp.setActivationPolicy(.accessory)

    That is what 0.9.19 still ships (CodeBurnApp.swift:92-96). So the app now sets .accessory before the status item exists, which is precisely the state #147 identified as causing "the scene is created but nothing draws". The two commits' rationales contradict each other and, as far as I can tell from the history, the second one was never re-tested against the original #146 regression.

    That would also explain why this reads as a #146 recurrence rather than a new failure mode.

    Caveat, and why I am commenting rather than sending a patch. I cannot reproduce it. On macOS 26.5.2 (25F84) with the same 0.9.19 build the icon renders normally for me, so whatever triggers it is narrower than "26.5.x", and flipping the ordering back blind risks reintroducing the ghost-status-item bug 85b5728 was fixing. There is also no automated coverage for this: StatusItemContextMenuPolicyTests states in its own comments that it does not drive a real NSStatusItem, so any change here ships on manual testing only.

    @twodxme, if you are willing to test a build, the useful experiment is to restore the 2268a8a ordering (start .regular, activate, set up the status item, then switch to .accessory one runloop turn later) and check two things: whether the icon comes back, and whether a ghost status item appears. That answers whether these two bugs are genuinely a see-saw or whether the ghost item had a different cause, which is the thing worth knowing before either ordering gets locked in.

  2. ozymandiashh commented on Aug 3, 2026

    @ozymandiashh
    Collaborator

    Correcting part of my own earlier comment, with new empirical data. I built a minimal probe bundle to test the lifecycle claims on macOS 26.5.2, and one load-bearing assumption turns out to be false.

    CodeBurnApp.swift:92-96 is dead code in every packaged build. Both mac/Scripts/package-app.sh:94 and mac/Scripts/build-local.sh:134 write <key>LSUIElement</key><true/> into Info.plist, so LaunchServices starts the process at .accessory before main() even runs. Measured: with LSUIElement=true, NSApp.activationPolicy() is already .accessory at applicationWillFinishLaunching, and NSApp.setActivationPolicy(.accessory) returns false (no state change). Remove LSUIElement and the same call returns true and flips 0 to 1.

    Two consequences:

    1. The rationale in db99319 ("setting the policy after didFinishLaunching bakes it into the initial focus chain") cannot be the mechanism that fixed the ghost item, because the policy was never being set late in shipped builds. The only real behavioral deltas of 85b5728/db99319 were (a) deleting NSApp.setActivationPolicy(.regular) + NSApp.activate(ignoringOtherApps: true) from didFinishLaunching (i.e. reverting the Fix NSStatusItem not rendering on macOS Tahoe (26.x) #147 fix for Menubar app: NSStatusItem created but never rendered on macOS 26.4 (Tahoe) #146), and (b) the 50ms debounce.

    2. That reframes the see-saw between Menubar app: NSStatusItem created but never rendered on macOS 26.4 (Tahoe) #146 and the ghost item. The ghost item was most plausibly caused by the .regular -> .accessory transition itself while a live NSStatusItem existed. Menubar app: NSStatusItem created but never rendered on macOS 26.4 (Tahoe) #146, by contrast, was the app never activating with the window server before creating the status item. Same lever, opposite ends, which is exactly why flipping it back and forth keeps trading one bug for the other.

    A testable middle path exists that flips neither side: keep the policy pinned at .accessory (never transition it) and restore only the activation half of #147. Concretely, one line in applicationDidFinishLaunching, immediately before the setupStatusItem() call (currently ~line 127):

    NSApp.activate(ignoringOtherApps: true)

    Accessory apps can activate without a policy change, so this reproduces the effect #147 actually needed (window-server registration before the status item is created) without the transition that db99319 removed for good reason.

    @twodxme since you offered to test a patched build: this is the build worth trying. I cannot reproduce the black icon here (same 0.9.19 bundle, macOS 26.5.2/25F84, renders fine), so I am deliberately not sending a blind PR. If the activate-only build fixes it on 25F80, the fix becomes evidence-backed and I am happy to turn it into a proper PR with the dead-code comment at :92-96 corrected as a separate cleanup.

  3. ozymandiashh commented on Aug 3, 2026

    @ozymandiashh
    Collaborator

    @twodxme the activate-only build described above is ready for the test you offered. One commit on top of current main, adding exactly one line before setupStatusItem():

    git clone -b experiment/868-activate-only https://github.com/ozymandiashh/codeburn.git codeburn-868
    cd codeburn-868 && ./mac/Scripts/build-local.sh
    

    The script assembles CodeBurnMenubar.app (path printed at the end). Quit the installed CodeBurn first so the two do not race for the status item, then launch the patched bundle.

    • Icon renders on 25F80: the fix is evidence-backed and I will send the PR (plus the separate dead-code comment correction at CodeBurnApp.swift:92-96).
    • Still black: that falsifies the activation hypothesis too, and the remaining suspects narrow considerably (the 50ms debounce, or something 25F80-specific below the app).

    Either result is informative, so whichever way it lands, thank you for running it.

  4. added a commit that references this issue on Aug 10, 2026
  5. iamtoruk commented on Aug 10, 2026

    @iamtoruk
    Member

    The activate-only fix is merged (#955, cherry-picked from the experiment branch with authorship preserved) and will ship in the next release, so testing no longer requires a local build: @twodxme, updating to the upcoming version and checking whether the icon renders on 25F80 is now the whole test. The issue stays open until that confirms or falsifies it. If the icon is still black on the release build, the activation hypothesis is falsified and the remaining suspects narrow to the 50ms debounce or something 25F80-specific below the app, per the analysis above.

  6. iamtoruk commented on Aug 10, 2026

    @iamtoruk
    Member

    0.9.20 is released with the activation fix (#955) in the menubar build. @twodxme the test is now just: codeburn menubar --force (or the in-app update), then check whether the icon renders on 25F80. Either result settles the hypothesis - please report back either way.

  7. ozymandiashh commented on Sep 12, 2026

    @ozymandiashh
    Collaborator

    The activation fix (#955) shipped in 0.9.20 on 2026-08-10 and no recurrence has been reported in the month since. Closing as fixed. If the icon still fails to render on 25F80 with a current build, please reopen with the log excerpt and we will pick it straight back up.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions