Ideally such a misdesigned API would not exist at all. Library interfaces should be engineered to prevent mistakes. Here are a handful of the problems I've run into recently when dealing with legacy OpenSSL code (legacy being the reason it uses OpenSSL, not the reason it was bad):
Some error codes are `int`s, other are `long`s. Different error codes need to be passed to different stringification functions, and these have different allocation and string-loading semantics. Why on earth do I have to manually load error strings in the first place? I don't pass a string-table handle into the stringification, so I don't even get context isolation (multiple instances of OpenSSL in one thread have conflicts)!
The entire BIO framework is insanely overcomplicated and could be stripped down to a minimal buffer-based encryption API (c.f. the BSD libtls API).
Then you have API like `SSL_CTX_set_verify` which simply ignores irrelevant flags rather than returning an error about them. This is terrible.
Nobody should use OpenSSL for new projects.