i'm increasingly growing fond of the API error handling style as it is done in GL 4; the idea being that you register a callback for things that went wrong, and then you can decide from there how to handle it: print a warning, log to file, abort (for debugger), longjmp, raise an error... it's more versatile than dealing with exceptions or return codes because you're still in the correct call stack for that error.
Note that to actually get your callback called from your offending gl* call (so you get a useful backtrace) you need to glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS)