Skip to content

Troubleshooting

ChiFungHillmanChan edited this page Oct 5, 2026 · 9 revisions

Troubleshooting

Build-time issues

swift test fails with "cannot find 'Slot' in scope"

You're running an old tests-first TDD checkpoint. Make sure all files in Sources/SceneCore/Layout/ are present:

ls Sources/SceneCore/Layout/
# Should contain: Slot.swift, Layout.swift, LayoutEngine.swift, Plan.swift, Geometry.swift

If missing, you've likely lost a commit. git log --oneline and rebase to main.

xcodebuild fails with errSecInternalComponent

macOS keychain can't access a signing identity. Work around by disabling signing for the local build:

xcodebuild … CODE_SIGNING_REQUIRED=NO build

Not needed for scripts/build-dmg.sh (already sets it).

errSecInternalComponent even with CODE_SIGNING_REQUIRED=NO

Unlock your login keychain:

security unlock-keychain ~/Library/Keychains/login.keychain-db

Then retry.

Xcode says "ObservableObject requires Combine" or "cannot find '@Published'"

A Swift source file declares @Published / ObservableObject without also importing SwiftUI. Add import Combine at the top. Files currently requiring this: SceneApp/SceneApp/AppDelegate.swift, SceneApp/SceneApp/Coordinator.swift.

project.pbxproj conflict after merging

The project uses Xcode 16+ Synchronized Groups (PBXFileSystemSynchronizedRootGroup). Swift files under SceneApp/SceneApp/ auto-add to the target — you shouldn't need to touch project.pbxproj when adding a new .swift file. If you hit a conflict anyway, rebuild in Xcode (⌘B) once — it'll regenerate the synchronized group.

Runtime issues

A gap at the bottom of my second monitor (v0.7.4+)

Expected, not a bug. Setpiece reserves the Dock's thickness on every display so that a layout's target rects stop depending on which display the Dock happens to be on — otherwise moving the Dock between monitors makes re-applying a layout shift every window.

If you want that space back, turn on System Settings → Desktop & Dock → Automatically hide and show the Dock. With auto-hide, macOS reserves nothing on any display, so layouts reach the screen edge with the stationary-re-apply guarantee intact.

Single-display Macs are unaffected — the reserve there is identical to visibleFrame.

Settings freezes, then "quit unexpectedly" (v0.8.0 on macOS 27)

Fixed in v0.8.1. On v0.8.0 under macOS 27, opening Settings froze the window (nothing could be clicked) and the app crashed a few seconds later, every time. Update from the menu bar: Update available lives in the menu bar panel, not in Settings, so it works even while Settings is crashing. The crash report shows NSGenericException with "more Update Constraints in Window passes than there are views in the window". Cause and fix are in Roadmap → Shipped in v0.8.1.

Menu bar icon doesn't appear

  • Check System Settings → Control Center — if "Menu Bar Only" section has too many items, some get hidden behind the clock. Try Bartender or drop an item.
  • Confirm you launched the built app, not from the mounted DMG. If you ran it from the DMG, macOS may have sandboxed it differently.
  • Force-quit with pkill -x SceneApp and relaunch.

First launch crashes / nothing happens

Check Xcode Console (Debug Area) for stack trace. Common causes:

  • Accessibility API called before the app got permission. Setpiece should gracefully open the onboarding window, not crash — file an issue with the stack trace.
  • CGWindowListCopyWindowInfo returned nil (extremely rare). Treated as EnumerationError.cgWindowListFailed.

Hotkeys stopped working after an update or rebuild

The most common cause since V0.4 is the TCC cdhash quirk: ad-hoc signed apps have the Accessibility grant tied to the binary's code-directory hash, and every rebuild invalidates the grant even though the toggle in System Settings still looks ON. Setpiece's 2-second AX poll then trips and hotkeys unregister.

Two fixes:

  1. Toggle OFF then ON again in System Settings → Privacy & Security → Accessibility for the Setpiece entry. Re-binds the grant to the current cdhash.
  2. Reset TCC: tccutil reset Accessibility com.hillman.SceneApp — forces a fresh prompt on the next AX call.

After either fix, the 2-second poll picks up the grant automatically and hotkeys come back.

Other possible causes (if neither TCC fix helps):

  • Granted to the wrong path: macOS tracks each bundle path separately. Run ps -ax | grep SceneApp — if the path differs from the /Applications/Scene.app entry in System Settings, grant permission to the current path.
  • Setpiece's menu bar dropdown shows "Grant Accessibility Access…" instead of the layout presets — the app detected permission loss. Re-grant in System Settings; Setpiece rehydrates within 2 s.

"SceneApp can't be opened because the developer cannot be verified"

Expected on first launch — the DMG is ad-hoc signed, not notarized. Either:

  • Right-click Scene.app → Open once (macOS remembers the exception).
  • Or: xattr -cr /Applications/Scene.app to strip the quarantine flag.

System Settings doesn't resize properly

Apple's System Settings.app has a hard minimum window size. AX setSize calls below that minimum are silently ignored. Setpiece still sets the position correctly; the window just doesn't shrink.

Not a bug. Document in the user-facing copy if this becomes a common support question. The same limitation affects Finder Get Info windows, Calculator, and some older Preferences-style apps.

V0.7.3 consequence. Sticky re-apply recognizes an already-placed window by comparing its frame to the slot rect (within 10 pt). A window that never reached its slot size therefore never matches, so re-firing a layout can still re-slot it while every compliant window stays put. Expected, same root cause.

Electron windows come out off-alignment

Cursor / VS Code / Slack etc. are expected to settle within ±5 px. If you see larger drift:

  • Confirm the app version. Older Electron builds had worse AX compliance.
  • Check Setpiece logs in Console.app (subsystem:com.scene.core category:layout-engine) — look for setFrame failed lines.
  • The tolerance retry fires once. Multiple retries tend to oscillate — we intentionally don't do more.

Permission-related

Accessibility toggle keeps turning itself off (TCC cdhash quirk)

This is the standard behavior of macOS's TCC database with ad-hoc signed apps: the Accessibility grant is tied to the binary's code-directory hash (cdhash), and every rebuild produces a new cdhash. The entry in System Settings → Privacy & Security → Accessibility still looks ON, but the running binary's cdhash no longer matches the cdhash that was granted — so AXIsProcessTrusted() returns false.

Two ways out:

  • Toggle OFF then ON again in System Settings (fastest — 2 seconds).
  • Reset TCC for Setpiece: tccutil reset Accessibility com.hillman.SceneApp, then relaunch Setpiece and accept the prompt.

For development: always run from the same path (Xcode's DerivedData, or /Applications/Scene.app if you install the DMG) to keep the cdhash stable where possible. Switching between Debug and Release builds, or rebuilding after a commit, will re-trigger the quirk.

Permanent fix is blocked on Apple Developer ID signing (V0.5 deferred) — real signatures have a stable identity that survives rebuilds; ad-hoc does not.

Granted permission but Setpiece still says it's denied

This is the classic AX trust trap — AXIsProcessTrusted() can return a stale false for the lifetime of the process when permission is granted while the app is running, even though Apple documents it as non-caching.

V0.2+ handles this automatically by using AXIsProcessTrustedWithOptions(prompt: false) (called forceRecheck() internally) for the 2-second poll loop and the onboarding "Check again" button. The grant should be detected within 2 seconds of toggling on in System Settings.

If it still fails to detect after a "Check again" click (rare — usually means macOS itself didn't refresh the trust DB, or the cdhash quirk above), the onboarding view shows the tccutil reset Accessibility com.hillman.SceneApp rescue command (with a one-tap Copy button) and a Quit Setpiece button. Since V0.5.4 the rescue block is visible from the moment the onboarding window opens — you don't need to click Check again first. Quitting and relaunching always works because the process restart re-reads the trust state from scratch.

For diagnosis:

# Confirm the running process bundle path matches the granted entry in System Settings
ps -ax | grep SceneApp
# If the path is different (e.g., /tmp/SceneBuild/... vs /Applications/SceneApp.app),
# you need to grant permission for the new path — System Settings tracks each path separately.

For V0.1 (pre-fix), there's no in-app workaround other than killing and relaunching:

pkill -x SceneApp
open /Applications/Scene.app

Packaging

build-dmg.sh produces a universal binary (V0.5.3+)

From V0.5.3 onwards, build-dmg.sh ships a universal binary (ARCHS="arm64 x86_64") so Intel Macs install from the same DMG. Verify:

lipo -info dist/Scene-<version>.dmg-contents/Scene.app/Contents/MacOS/SceneApp
# Architectures in the fat file: ... x86_64 arm64

If you want an arm64-only build (slightly smaller DMG), replace ARCHS="arm64 x86_64" with ARCHS="arm64" in scripts/build-dmg.sh.

SWIFT_OPTIMIZATION_LEVEL=-Onone in build-dmg.sh (V0.5.3+, Xcode 26 workaround)

Xcode 26.x's Swift Release optimizer (-O / -Osize) crashes with an internal compiler error in the SIL pipeline when the deployment target is any pre-macOS-26 version (including 14.0, which is Setpiece's minimum). build-dmg.sh forces SWIFT_OPTIMIZATION_LEVEL=-Onone as a workaround. Binary-size and runtime-cost impact are negligible for Setpiece's mostly-I/O workload. Remove the override once a fixed Swift toolchain ships.

hdiutil create says the volume name is too long

hdiutil volume names cap at 27 characters. Use Setpiece <version> (e.g., Setpiece 0.4.0) — stays under.

Clone this wiki locally