The reason for this is that $regex() can fail for many reasons not related to PCRE. In the original implementation, the PCRE code was basic enough that this was not the case. But as it became more complicated, many other error contexts arose. To maintain backwards compatibility, it continued to return the execution error if there was one. But it defaults to PCRE_ERROR_INTERNAL in most other failure cases. It also returns error values from other PCRE calls. So the returned error value can actually be due to a number of APIs and contexts. It was never documented because of this. The most you can depend on with the return value is that if it is negative, it indicates an error.