OBJC_DEBUG_MISSING_POOLS
June 12, 2026 -TIL about OBJC_DEBUG_MISSING_POOLS=Yes.
I was on a small side mission to build a macOS taskbar widget to visualize when my external display and Mac don't correctly negotiate to use USB3.1 (renege)1. This manifests itself as my CamLink 4k not being connected with USB3.1, which is the signal that I'm currently looking for.
My goal, as with all side projects, was to implement it in Rust. I did some Objective C back at university, but it's been a long time. I used Claude to guide me through what I needed to do and implement. Once again it's amazing how far using AI tooling can get you without much domain-specific knowledge, and as we shall see, how easy you can shoot yourself in the foot because of a lack of proper understanding.
I ended up using the Rust bindings to AppKit, IOKit, CoreFoundation, et. al., which are very unsafe, and require a very different mental model of memory and ownership than Rust (obviously).
I was trying to understand the myriad of unsafe required to interface with AppKit, IOKit, etc. I got some review feedback from Claude that the icon that I was displaying in the status bar would not be rendered because its container would be dropped (because it had no remaining references).
But it was rendering properly. Claude suggested to run the application with OBJC_DEBUG_MISSING_POOLS=Yes on, which spewed out a ton of logs, mostly complaining about things leaking.
It turned out that the reason the icon was still rendering was because the runtime was leaking the item, because I didn't correctly configure the application (Cocoa expects an NSAutoReleasePool 2 to be available to it, if there is none, it leaks everything that should have been autoreleased).
Running all of the application initialization in an autoreleasepool reliably caused the icon to disappear. Hurrah! I guess...
So why was the icon's container being released? Basically because I hadn't grokked the AppKit APIs, so my implementation was holding on to the wrong reference. To show something in the status bar, one must get the global NSStatusBar instance, and then add an NSStatusItem to the status bar, and hold onto it.
Coming back to OBJC_DEBUG_MISSING_POOLS=Yes; there is a huge amount of runtime information that one can expose for Objective-C programs. To get an overview, run an AppKit binary with the OBJC_HELP=1 env var set. The rest is an exercise for the reader.
Note: This post was written solely by a human (me).