10

This should be the easiest thing to do, but for some reason I just can't get it done.

I'm trying to get a friendly static error page to replace nasty 500 scenarios. For now I'm just trying to replicate a 500 situation on my local machine (Drupal 7 running on MAMP) by throwing in some crap characters on the top of my template.php in my theme, which does trigger a 500 situation, but for some reason the ErrorDocument directive in my .htaccess or Apache config file has no effect.

What I'm doing is quite simply this:

ErrorDocument 500 /500.html

And I have the simplest ever static html-page in the root of my site with the name of 500.html.

Still, when I intentionally break template.php, I get the dreaded White Screen Of Death instead of my nice friendly error page.

What am I doing wrong here? I've done this a billion times in non-Drupal setups but just can't get my head around this one.


UPDATE: It seems this questions is pretty much redundant in my specific use case right now as Acquia's Dev Cloud that we use to run the application in question doesn't even support customizing 500-series error pages at the moment. Here's hoping they'll implement support for that soon.

  • What happens if you add drupal_add_http_header('Status', '503 Service Unavailable'); to your 500.html? – amateur barista Jul 16 '12 at 17:10
2

500 error pages are strictly server error pages. Once the server hands off execution to PHP, Drupal/PHP are responsible for serving their own error page. You might try telling Drupal to redirect the user to a custom error page, along with an HTTP 500 status header, when it receives certain errors within a try...catch block.

However, note that some WSODs can occur at the system level and they could cause a fatal error that immediately halts execution and possibly prevent the catch to execute. One example of this is when your database is not properly tuned to handle queries of certain size (like when doing a Features revert all operation) - the database may choke up, giving you an insta-WSOD.

I'd say the best thing to do is check your apache, MySQL and PHP error logs, and try to isolate the root cause of WSOD on a case-by-case basis, as opposed to trying to cover them up with a pretty-error page. While the errors that cause the typical 500 server error pages sometimes are unavoidable, and having custom server error pages in production is feasible, having WSODs happening live is not.

It looks like you have the server error pages set up properly. You just need to make the distinction that typical server error pages != WSODs. Server error pages can be triggered because of high traffic and resource bottlenecks, but you shouldn't really be having WSODs happen in production, period. These typically happen because of poor coding, optimization or configuration. If you still see an WSOD, make sure you find (and solve) the root cause of the problem first, as opposed to trying to apply a band-aid to it.

  • 4
    Thanks for your answer. You're absolutely right about root cause / treating symptoms. This is however irrelevant to the need of nice error pages as it's a fact that during the lifespan of a service, errors will happen and in those situations it's always better to communicate the situation to users nicely rather than with blank pages or generic black on white "server error" pages. The Twitter fail whale as an example. That doesn't remove the need for professional error profiling, but on the interim, makes users less angry. – Tommi Forsström Jul 10 '12 at 21:22
  • 1
    Also, for this case there is no need to differentiate between the layers from which the error originates (as long as it's beneath the http server) as I just need a catch-all mechanisms for errors in the application layer, whether it's the database crashing, somebody committing crap code (and that passing our test coverage) and any other conceivable yet unexpected error situation. But as updated in the question, this is irrelevant for me at the moment as Acquia's dev cloud doesn't support customizing 500-series error pages at the moment. – Tommi Forsström Jul 10 '12 at 21:30
  • "Acquia's dev cloud doesn't support customizing 500-series error pages at the moment." Aww shucks, that's good to know. – amateur barista Jul 16 '12 at 17:08
  • Although that's almost the only fly in the ointment with Acquia's mighty Dev Cloud and they also might implement this in the near future. I can't speak highly enough for the Dev Cloud. It's an amazing platform to run Drupal services on! – Tommi Forsström Jul 24 '12 at 1:57
1

You are getting WSOD because you turned error reporting off in php.ini. This is a security issue - if you have an error and hacker sees what it is, he may potentially use it to hack the site.

If you want to intercept the error, though, you need to enable showing the errors in php.ini (the example will only show serious errors):

error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT

And then, you can set the error documents in the htaccess file:

ErrorDocument 401 http://yourwebsite.com/error-401
ErrorDocument 403 http://yourwebsite.com/error-403
ErrorDocument 500 http://yourwebsite.com/error-500

Alternatively, you can specify the errors in Drupal's settings.php file.

In NGINX:

error_page 403 = /error.php?code=403;   
error_page 404 = /error.php?code=404;
error_page 500 = /error.php?code=500;

Since you are running Apache in MAMP, set it in .htaccess. Remember that AllowOverride in apache config should be on (usually it is).

  • setting a ErrorDocument directive for 500 responses in Drupal does not work in my testing – cdmo Jul 6 '16 at 18:49
  • 500 Errors usually can't be set in Drupal. They need to be set before Drupal - in .htaccess if using Apache. In NGINX - see the updated ticket. – Alexei Rayu Jul 7 '16 at 5:25
  • That's what I meant. Have you been able to get an ErrorDocument directive for 500 errors set in an htaccess or a vhost configure to actually work for a Drupal site? Those directives are ignored in my experience, Drupal takes over error handling. – cdmo Jul 7 '16 at 10:40
0

Have you turned error reporting on? (admin/config/development/logging -> Set All messages for Error messages to display)

By default, Drupal shows a WSOD as a security feature.

  • Funny enough, that is turned on and I still get WSOD. – Tommi Forsström Jun 28 '12 at 15:07
  • In that case it's likely a MAMP issue, not a Drupal problem. Try turning on error reporting in php.ini (forum.mamp.info/viewtopic.php?f=2&t=8077) Error display is disabled in MAMP by default. – Patrick Kenny Jun 28 '12 at 15:21
  • 1
    I can get php errors displayed fine. That's not really the issue. I want to be able to display something friendly when errors happen, like Twitter's Fail Whale. That's the thing I can't make happen: custom error pages for 500-series errors. – Tommi Forsström Jun 28 '12 at 15:44
0

I guess the answer is "read the docs", see https://www.drupal.org/node/195435

So basically you can create the template files named maintenance-page.tpl.php and maintenance-page--offline.tpl.php and hard code some settings in settings.php.

EDIT:

It doesn't seem to matter what level error_reporting is set to or whether you have set display_errors to on or off. When you have a maintenance-page--offline.tpl.php file in place Drupal will display this page when the database goes away. Also doesn't matter what you have set at /admin/config/development/logging in the admin side. If you just have syntax errors, which was the OP's situation, that won't actually trigger a 500, it's a 200 with a PHP error either displayed or hidden based on the php.ini display_error set. There is no way, that I know of, other than to add your custom error handling logic throughout your custom code as needed.

  • Not sure why I got downvoted here, this is the answer I was looking for when I set the bounty. One other not for the OP, you can set error_prepend and append on standard PHP error notices too if you wanted to elaborate your standard error page further. – cdmo Jul 11 '16 at 11:59
0

To replace all WSOD with something else would require hacking core: you do not want to do this. Drupal defines its own error handlers in bootstrap.inc and errors.inc. If you were to mess around with that code you would have to make sure you accounted for all the things that could be wrong when execution reached this stage (no database, no theme engine, no theme, no config, etc).

  • Ever tried to use PHP's error_append and error_prepend options? While the error message would still display, it seems like you could offer a much nicer 500 experience (granted, not all PHP errors that make a whitescreen technically cause a 500 response, like many syntax errors.) – cdmo Jul 11 '16 at 12:02
  • True. Either way gets you to the same general point: you can't do that. – acrosman Jul 11 '16 at 13:00
0

I made a sandbox project to do this.

I was able to accomplish this by extending the HttpExceptionSubscriberBase in /src/EventSubscriber/fivehundredEventSubscriber.php

    <?php
namespace Drupal\five_hundred\EventSubscriber;

use Drupal\Core\EventSubscriber\HttpExceptionSubscriberBase;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\Serializer\SerializerInterface;

class five_hundredEventSubscriber extends HttpExceptionSubscriberBase {

      public function __construct($stack) {

        if(
          (
            null !== $stack->getCurrentRequest()->attributes->get('exception')->getCode()
            && $stack->getCurrentRequest()->attributes->get('exception')->getCode() == 500
          )||(
            null !== $stack->getCurrentRequest()->attributes->get('exception')->getStatusCode()
            && $stack->getCurrentRequest()->attributes->get('exception')->getStatusCode() == 500
          )
        ){
            $response = new Response();
            $errorDocumentHtml = 'html here';
            $response->setContent($errorDocumentHtml);
            $response->setStatusCode(500, '500 Internal Server Error');
            $response->send();
            die();
        }
      }

      /**
       * {@inheritdoc}
       */
      protected function getHandledFormats() {
        return array('html','');
      }


    }
?>

And you'll need to add the service in your module.services.yml

services:
  five_hundred.:
    class: Drupal\five_hundred\EventSubscriber\five_hundredEventSubscriber
    arguments: ['@request_stack']
    tags:
      - { name: event_subscriber }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.