Day 133: Two Companies, One Journal Name
The Penny bookkeeping agent on pinchy.heypinchy.com got stuck trying to do something that should take one call: post an opening balance to an account. Instead it spent about two hours throwing roughly thirty different attempts at a single field, journal_id, and getting a different rejection each time. Reading the trail afterward was like watching someone try every key on a ring while the lock quietly told them “wrong” without saying why.
Thirty wrong keys
The agent tried the numeric id, and the anti-enumeration guard correctly refused it (“Raw numeric IDs are not accepted”). It tried the opaque Pinchy reference and got “Could not resolve.” It tried the journal’s name, “Miscellaneous Operations,” and got “multiple records match.” It tried the code, “SONST,” and got “Could not resolve.” At one point it invented a name that stitched the code and the company together, which no lookup would ever match. Every attempt was reasonable. Every attempt failed, and none of the failures pointed at the actual problem.
A name is not an identity
The real cause was two bugs braided together (PR #614). The first is a fact about Odoo that a naive lookup ignores: journal codes and names are unique per company, not globally. This instance has two companies, and each one owns a journal named “Miscellaneous Operations” with the code “SONST.” So a lookup by name or code was ambiguous by construction. “Multiple records match” wasn’t a fluke, it was the only honest answer to a question that didn’t say which company it meant.
The second bug is why the escape hatch didn’t save it. The tool prose tells the agent, when a name is ambiguous, to pass an opaque Pinchy reference verbatim and let Pinchy resolve it to the right record. That is the designed way out. But the resolver didn’t handle that reference when it arrived bare in a many-to-one field, which is exactly the field type the whole mechanism exists for. So the one door built for this situation was locked. The fix resolves the bare reference where the field type needs it, and scopes every journal lookup by the company on the record being written, so “Miscellaneous Operations” resolves to the one that belongs to the right set of books.
Day 133
Multi-company isolation is not a feature you bolt on, it is a boundary that has to hold at every lookup, or it holds at none of them. This is the same idea that runs under Pinchy’s permissions model: a name, a label, a reference is only meaningful inside the scope that owns it, and the moment you let a lookup float free of its scope, you get either an ambiguous failure like this one or, far worse, a confident write to the wrong company’s books. Penny thrashed for two hours because a name was being treated as an identity. The agent looked incompetent. The tool was.