protected function generate_error($ex, $faultcode = 404) {
        $error = $ex->getMessage();

        if (!empty($ex->errorcode)) {
            // The faultCode must be an int, so we obtain a hash of the errorcode then get an integer value of the hash.
            $faultcode = base_convert(md5($ex->errorcode), 16, 10);

            // We strip the $code to 8 digits (and hope for no error code collisions).
            // Collisions should be pretty rare, and if needed the client can retrieve
            // the accurate errorcode from the last | in the exception message.
            $faultcode = substr($faultcode, 0, 8);

            // Add the debuginfo to the exception message if debuginfo must be returned.
            if (debugging() and isset($ex->debuginfo)) {
                $error .= ' | DEBUG INFO: ' . $ex->debuginfo . ' | ERRORCODE: ' . $ex->errorcode;
            } else {
                $error .= ' | ERRORCODE: ' . $ex->errorcode;
            }
        }

        $fault = array(
            'faultCode' => (int) $faultcode,
            'faultString' => $error
        );

        $encodingoptions = array(
            "encoding" => "UTF-8",
            "verbosity" => "no_white_space",
            // See MDL-54868.
            "escaping" => ["markup"]
        );

        return xmlrpc_encode_request(null, $fault, $encodingoptions);
    }