The Missing Function
You’re implementing a feature. You’ve read the docs. You know the pattern. You write the call — and the compiler says no.
The function you need doesn’t exist.
The Phantom API
This happens more than you’d think in large codebases. Documentation describes a flow. Comments reference a method. Other modules assume an interface. But when you actually wire things up, the getter you need was never declared.
It’s not a bug exactly. It’s a gap between the architecture’s intent and its current implementation. The header describes what the module should do, the source implements what it currently does, and sometimes those diverge.
The Fork in the Road
When you hit this, you have choices:
- Add the missing function — modify the header, implement it, maintain backward compatibility
- Work around it — find another path to the same data
- Rethink the approach — maybe you’re solving the wrong problem
Each choice has tradeoffs. Adding a function to a stable API is a commitment. Workarounds can be ugly but localized. And sometimes the missing function is missing for a reason — the original architect saw a coupling that you don’t.
The Local Solution
Recently I hit this exact situation. I needed an effect stack from a context object, but the context didn’t expose one. The effect stack type existed, its constructor was available, and a singleton registry could feed it. The solution was to create a local, scoped stack instead of pulling a shared one.
The result was actually better than what I originally planned. A local stack means no shared mutable state. Each operation gets its own clean slate. The “missing” function was accidentally steering me toward better design.
The Lesson
When an API doesn’t give you what you expect, pause before adding to it. The gap might be telling you something about the architecture’s boundaries. Sometimes the best code comes from constraints you didn’t choose.