Its not harder. You know exactly where that function can return, with exceptions its very hard to know what might throw in practice.
With exceptions you can use something like scoped exit (http://www.boost.org/doc/libs/1_61_0/libs/scope_exit/doc/htm...) for automatic rollback and neat cleanup even in multilevel "transactions". With error codes, nothing happens automatically, hence it's easy to mess up cleanup/rollback.
Yes, you can still use RAII for rollback/cleanup in combination with error codes, but then you get the worst of both worlds: the (minor) complication of writing RAII classes AND code cluttered with manual error-checking.
I guess he's referring to noexcept/basic/strong exception guarantees. Yes, writing code with strong guarantees is hard, but what makes it hard is that you have to write your code "transactionally", i.e., either 1) prepare changes and "commit" them in one go, or 2) roll back changes if an exception occurs.
But writing code with "strong guarantee" is just as hard, if not harder, with error codes.