Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keeping ErrorHandler::class in ZE3 pipeline.php hides descriptive error messages #49

Closed
4 tasks done
dennis-fedco opened this issue Jul 3, 2018 · 6 comments
Closed
4 tasks done
Labels

Comments

@dennis-fedco
Copy link

dennis-fedco commented Jul 3, 2018

What ZF application I'm using when issue happen ?

  • Expressive 3

What PHP version you're using?

  • PHP 7.2

What ErrorHeroModule version you're using?

  • ^2.0

What Database you're using?

  • MySQL version 8.0.11

Expected behavior

Upon a PHP error, show a meaningful descriptive error message from PHP, pointing to the root cause of web page malfunction. i.e. Fatal error: [description ... ].

Actual behavior

Browser displays the following message:

Oops!
This is awkward.

We encountered a 500 Internal Server Error error.

There are no further clues to the error message in the Apache error log. There is nothing in Mozilla's Developer Tools. Nothing seems to get logged via the ErrorHeroModuleLogger in the database table.

Steps/Codes to reproduce the behavior

In my pipeline.php I have the following:

$app->pipe(ErrorHandler::class); //Zend\Stratigility\Middleware\ErrorHandler
$app->pipe(ErrorHeroModule\Middleware\Expressive::class);

I suspect that whatever the error is, it gets eaten up by the ErrorHandler::class and the generic message above is displayed, hiding the real error description.

Potential Solution: Removing the ErrorHandler::class from pipeline.php uncovers the descriptive error and displays the full error message from PHP that I am looking for.

Summary

It seems to me that the line of $app->pipe(ErrorHandler::class) is the culprit in covering up descriptive error messages. Removing it resolves my immediate issue and shows me the descriptive errors I was looking for. Can ErrorHandler::class be removed? Must it remain in Expressive pipeline config and if yes can I still see descriptive error messages?

@dennis-fedco dennis-fedco changed the title Keeping ErrorHandler::class in ZE3 pipeline.php hides descriptive error messages Keeping ErrorHandler::class in ZE3 pipeline.php hides descriptive error messages Jul 3, 2018
@samsonasik
Copy link
Owner

I tried with php 7.2, latest expressive 3 skeleton, latest ErrorHeroModule, and it works fine with the following steps:

  1. install skeleton
$ composer create-project zendframework/zend-expressive-skeleton expressive3-test
    1/8:	http://packagist.org/p/provider-latest$7f68507803f191a7427d67bb551ed7c16dffb2c8847bc0871515d85f1335a536.json
    2/8:	http://packagist.org/p/provider-2014$071ad4bcb474a6e381fdf72c1edb120c1ce8d5ee57f75b8d5be7c4950d4f549f.json
    3/8:	http://packagist.org/p/provider-2018-04$c10e8d6d1331a4ab157a10291cfb54b9186bb3ae91796092c9fdb24102b536b0.json
    4/8:	http://packagist.org/p/provider-2015$f0c099fa3619c09645d99255b25e8b3e58a71b243b2567e640de1f4df2942a7f.json
    5/8:	http://packagist.org/p/provider-2018-01$4535d6d33ff5178fa355f9f27f5b8685a5a3a7f4d2f579f5f30a17acaf11d572.json
    6/8:	http://packagist.org/p/provider-2017-10$a7c8dbbcddd14f86805215ce2d4f2ed2ce6b8101fac72d62a3f2fb52bb3a9267.json
    7/8:	http://packagist.org/p/provider-2017$1771e8a94be345aa9e8b17ac6ca33c1e0f5236808f34c50e121355e26b9ddcfa.json
    8/8:	http://packagist.org/p/provider-2016$64ac8aae772112fc158dcb706d917524a8a6966fc28065585011b7f28dc39d0b.json
    Finished: success: 8, skipped: 0, failure: 0, total: 8
Installing zendframework/zend-expressive-skeleton (3.1.0)
  - Installing zendframework/zend-expressive-skeleton (3.1.0): Loading from cache
Created project in expressive3-test
> ExpressiveInstaller\OptionalPackages::install
Setting up optional packages
Setup data and cache dir
Removing installer development dependencies

  What type of installation would you like?
  [1] Minimal (no default middleware, templates, or assets; configuration only)
  [2] Flat (flat source code structure; default selection)
  [3] Modular (modular source code structure; recommended)
  Make your selection (2): 
  - Copying src/App/ConfigProvider.php

  Which container do you want to use for dependency injection?
  [1] Aura.Di
  [2] Pimple
  [3] zend-servicemanager
  [4] Auryn
  [5] Symfony DI Container
  [6] PHP-DI
  Make your selection or type a composer package name and version (zend-servicemanager): 3
  - Adding package zendframework/zend-servicemanager (^3.3)
  - Copying config/container.php

  Which router do you want to use?
  [1] Aura.Router
  [2] FastRoute
  [3] zend-router
  Make your selection or type a composer package name and version (FastRoute): 3
  - Adding package zendframework/zend-expressive-zendrouter (^3.0)
  - Whitelist package zendframework/zend-expressive-zendrouter
  - Copying config/routes.php

  Which template engine do you want to use?
  [1] Plates
  [2] Twig
  [3] zend-view installs zend-servicemanager
  [n] None of the above
  Make your selection or type a composer package name and version (n): 3
  - Adding package zendframework/zend-expressive-zendviewrenderer (^2.0)
  - Whitelist package zendframework/zend-expressive-zendviewrenderer
  - Copying templates/error/404.phtml
  - Copying templates/error/error.phtml
  - Copying templates/layout/default.phtml
  - Copying templates/app/home-page.phtml

  Which error handler do you want to use during development?
  [1] Whoops
  [n] None of the above
  Make your selection or type a composer package name and version (Whoops): 1
  - Adding package filp/whoops (^2.1.12)
  - Copying config/autoload/development.local.php.dist
Remove installer
Removing composer.lock from .gitignore
Removing Expressive installer classes, configuration, tests and docs
Loading composer repositories with package information
Updating dependencies (including require-dev)
    1/1:	https://codeload.github.com/Roave/SecurityAdvisories/legacy.zip/5c802c6300dca269edde06c6ae8c7eb561de3176
    Finished: success: 1, skipped: 0, failure: 0, total: 1
Package operations: 66 installs, 0 updates, 0 removals
  - Installing zendframework/zend-component-installer (2.1.1): Loading from cache
  - Installing ocramius/package-versions (1.3.0): Loading from cache
  - Installing zendframework/zend-stdlib (3.2.0): Loading from cache
  - Installing psr/container (1.0.0): Loading from cache
  - Installing container-interop/container-interop (1.2.0): Loading from cache
  - Installing zendframework/zend-servicemanager (3.3.2): Loading from cache
  - Installing zendframework/zend-validator (2.10.2): Loading from cache

  Please select which config file you wish to inject 'Zend\Validator\ConfigProvider' into:
  [0] Do not inject
  [1] config/config.php
  Make your selection (default is 1):1

  Remember this option for other packages of the same type? (Y/n)Y
    Installing Zend\Validator\ConfigProvider from package zendframework/zend-validator
  - Installing zendframework/zend-escaper (2.6.0): Loading from cache
  - Installing zendframework/zend-uri (2.6.1): Loading from cache
  - Installing zendframework/zend-loader (2.6.0): Loading from cache
  - Installing zendframework/zend-http (2.8.0): Loading from cache
  - Installing zendframework/zend-router (3.1.0): Loading from cache
    Installing Zend\Router\ConfigProvider from package zendframework/zend-router
  - Installing psr/http-message (1.0.1): Loading from cache
  - Installing zendframework/zend-diactoros (1.8.0): Loading from cache
  - Installing zendframework/zend-psr7bridge (1.0.2): Loading from cache
  - Installing psr/http-server-handler (1.0.0): Loading from cache
  - Installing psr/http-server-middleware (1.0.0): Loading from cache
  - Installing fig/http-message-util (1.1.2): Loading from cache
  - Installing zendframework/zend-expressive-router (3.1.0): Loading from cache
  - Installing zendframework/zend-expressive-zendrouter (3.0.0): Loading from cache
    Installing Zend\Expressive\Router\ZendRouter\ConfigProvider from package zendframework/zend-expressive-zendrouter
  - Installing zendframework/zend-eventmanager (3.2.1): Loading from cache
  - Installing zendframework/zend-view (2.10.0): Loading from cache
  - Installing zendframework/zend-expressive-template (2.0.0): Loading from cache
  - Installing zendframework/zend-expressive-helpers (5.1.0): Loading from cache
  - Installing zendframework/zend-expressive-zendviewrenderer (2.0.0): Loading from cache
    Installing Zend\Expressive\ZendView\ConfigProvider from package zendframework/zend-expressive-zendviewrenderer
  - Installing squizlabs/php_codesniffer (2.9.1): Loading from cache
  - Installing zendframework/zend-config-aggregator (1.1.1): Loading from cache
  - Installing zendframework/zend-httphandlerrunner (1.0.1): Loading from cache
    Installing Zend\HttpHandlerRunner\ConfigProvider from package zendframework/zend-httphandlerrunner
  - Installing sebastian/version (2.0.1): Loading from cache
  - Installing sebastian/resource-operations (1.0.0): Loading from cache
  - Installing sebastian/recursion-context (3.0.0): Loading from cache
  - Installing sebastian/object-reflector (1.1.1): Loading from cache
  - Installing sebastian/object-enumerator (3.0.3): Loading from cache
  - Installing sebastian/global-state (2.0.0): Loading from cache
  - Installing sebastian/exporter (3.1.0): Loading from cache
  - Installing sebastian/environment (3.1.0): Loading from cache
  - Installing sebastian/diff (3.0.1): Loading from cache
  - Installing sebastian/comparator (3.0.1): Loading from cache
  - Installing phpunit/php-timer (2.0.0): Loading from cache
  - Installing phpunit/php-text-template (1.2.1): Loading from cache
  - Installing phpunit/php-file-iterator (2.0.1): Loading from cache
  - Installing theseer/tokenizer (1.1.0): Loading from cache
  - Installing sebastian/code-unit-reverse-lookup (1.0.1): Loading from cache
  - Installing phpunit/php-token-stream (3.0.0): Loading from cache
  - Installing phpunit/php-code-coverage (6.0.7): Loading from cache
  - Installing doctrine/instantiator (1.1.0): Loading from cache
  - Installing webmozart/assert (1.3.0): Loading from cache
  - Installing phpdocumentor/reflection-common (1.0.1): Loading from cache
  - Installing phpdocumentor/type-resolver (0.4.0): Loading from cache
  - Installing phpdocumentor/reflection-docblock (4.3.0): Loading from cache
  - Installing phpspec/prophecy (1.7.6): Loading from cache
  - Installing phar-io/version (1.0.1): Loading from cache
  - Installing phar-io/manifest (1.0.1): Loading from cache
  - Installing myclabs/deep-copy (1.8.1): Loading from cache
  - Installing phpunit/phpunit (7.2.6): Loading from cache
  - Installing zfcampus/zf-composer-autoloading (2.1.0): Loading from cache
  - Installing zendframework/zend-stratigility (3.0.1): Loading from cache
  - Installing zendframework/zend-expressive (3.0.2): Loading from cache
  - Installing zendframework/zend-code (3.3.0): Loading from cache
  - Installing symfony/polyfill-mbstring (v1.8.0): Loading from cache
  - Installing symfony/console (v4.1.1): Loading from cache
  - Installing psr/log (1.0.2): Loading from cache
  - Installing zendframework/zend-expressive-tooling (1.0.1): Loading from cache
  - Installing zfcampus/zf-development-mode (3.2.0): Loading from cache
  - Installing filp/whoops (2.2.0): Loading from cache
zendframework/zend-servicemanager suggests installing ocramius/proxy-manager (ProxyManager 1.* to handle lazy initialization of services)
zendframework/zend-validator suggests installing zendframework/zend-db (Zend\Db component, required by the (No)RecordExists validator)
zendframework/zend-validator suggests installing zendframework/zend-filter (Zend\Filter component, required by the Digits validator)
zendframework/zend-validator suggests installing zendframework/zend-i18n (Zend\I18n component to allow translation of validation error messages)
zendframework/zend-validator suggests installing zendframework/zend-math (Zend\Math component, required by the Csrf validator)
zendframework/zend-validator suggests installing zendframework/zend-i18n-resources (Translations of validator messages)
zendframework/zend-validator suggests installing zendframework/zend-session (Zend\Session component, ^2.8; required by the Csrf validator)
zendframework/zend-http suggests installing paragonie/certainty (For automated management of cacert.pem)
zendframework/zend-router suggests installing zendframework/zend-i18n (^2.7.4, if defining translatable HTTP path segments)
zendframework/zend-expressive-router suggests installing zendframework/zend-expressive-aurarouter (^3.0 to use the Aura.Router routing adapter)
zendframework/zend-expressive-router suggests installing zendframework/zend-expressive-fastroute (^3.0 to use the FastRoute routing adapter)
zendframework/zend-view suggests installing zendframework/zend-authentication (Zend\Authentication component)
zendframework/zend-view suggests installing zendframework/zend-feed (Zend\Feed component)
zendframework/zend-view suggests installing zendframework/zend-filter (Zend\Filter component)
zendframework/zend-view suggests installing zendframework/zend-i18n (Zend\I18n component)
zendframework/zend-view suggests installing zendframework/zend-json (Zend\Json component)
zendframework/zend-view suggests installing zendframework/zend-mvc (Zend\Mvc component)
zendframework/zend-view suggests installing zendframework/zend-navigation (Zend\Navigation component)
zendframework/zend-view suggests installing zendframework/zend-paginator (Zend\Paginator component)
zendframework/zend-view suggests installing zendframework/zend-permissions-acl (Zend\Permissions\Acl component)
zendframework/zend-expressive-template suggests installing zendframework/zend-expressive-platesrenderer (^2.0 to use the Plates template renderer)
zendframework/zend-expressive-template suggests installing zendframework/zend-expressive-twigrenderer (^2.0 to use the Twig template renderer)
zendframework/zend-config-aggregator suggests installing zendframework/zend-config (Allows loading configuration from XML, INI, YAML, and JSON files)
zendframework/zend-config-aggregator suggests installing zendframework/zend-config-aggregator-modulemanager (Allows loading configuration from zend-mvc Module classes)
zendframework/zend-config-aggregator suggests installing zendframework/zend-config-aggregator-parameters (Allows usage of templated parameters within your configuration)
sebastian/global-state suggests installing ext-uopz (*)
phpunit/phpunit suggests installing phpunit/php-invoker (^2.0)
zendframework/zend-expressive suggests installing zendframework/zend-auradi-config (^1.0 to use Aura.Di dependency injection container)
zendframework/zend-expressive suggests installing zendframework/zend-pimple-config (^1.0 to use Pimple for dependency injection container)
zendframework/zend-code suggests installing doctrine/annotations (Doctrine\Common\Annotations >=1.0 for annotation features)
symfony/console suggests installing psr/log-implementation (For using the console logger)
symfony/console suggests installing symfony/event-dispatcher ()
symfony/console suggests installing symfony/lock ()
symfony/console suggests installing symfony/process ()
filp/whoops suggests installing symfony/var-dumper (Pretty print complex values better with var-dumper available)
filp/whoops suggests installing whoops/soap (Formats errors as SOAP responses)
Writing lock file
Generating autoload files
ocramius/package-versions:  Generating version class...
ocramius/package-versions: ...done generating version class
> zf-development-mode enable
You are now in development mode.
  1. setup db config/autoload/local.php
<?php
// config/autoload/local.php
return [
    'db' => [
        'username' => 'root',
        'password' => '',
        'driver'   => 'pdo_mysql',
        'database' => 'expressive',
        'host'     => 'localhost',
        'driver_options' => [
            \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'',
        ],
    ],
];
  1. composer require it
$ composer require samsonasik/error-hero-module
    1/2:	http://packagist.org/p/provider-latest$cb15031bc52a501c4bc5b397814f257a49a6ea441bb0cd38379658b7f06bc73c.json
    2/2:	http://packagist.org/p/provider-2016$132f4da511a49a4e012b9f85eb972b1eb93896b9f1a5a29f21ee917cd722c556.json
    Finished: success: 2, skipped: 0, failure: 0, total: 2
Using version ^2.12 for samsonasik/error-hero-module
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
    1/1:	https://codeload.github.com/samsonasik/ErrorHeroModule/legacy.zip/a6279900b9e5ec4877f440446887d1e4b458ccbc
    Finished: success: 1, skipped: 0, failure: 0, total: 1
Package operations: 9 installs, 0 updates, 0 removals
  - Installing zendframework/zend-text (2.7.0): Loading from cache
  - Installing zendframework/zend-mime (2.7.1): Loading from cache
  - Installing true/punycode (v2.1.1): Loading from cache
  - Installing zendframework/zend-mail (2.10.0): Loading from cache

  Please select which config file you wish to inject 'Zend\Mail\ConfigProvider' into:
  [0] Do not inject
  [1] config/config.php
  Make your selection (default is 1):1

  Remember this option for other packages of the same type? (Y/n)Y
    Installing Zend\Mail\ConfigProvider from package zendframework/zend-mail
  - Installing zendframework/zend-log (2.10.0): Loading from cache
    Installing Zend\Log\ConfigProvider from package zendframework/zend-log
  - Installing zendframework/zend-db (2.9.3): Loading from cache
    Installing Zend\Db\ConfigProvider from package zendframework/zend-db
  - Installing seld/jsonlint (1.7.1): Loading from cache
  - Installing beberlei/assert (v2.9.6): Loading from cache
  - Installing samsonasik/error-hero-module (2.12.0): Loading from cache
zendframework/zend-mail suggests installing zendframework/zend-crypt (Crammd5 support in SMTP Auth)
zendframework/zend-log suggests installing ext-mongo (mongo extension to use Mongo writer)
zendframework/zend-log suggests installing zendframework/zend-console (Zend\Console component to use the RequestID log processor)
zendframework/zend-db suggests installing zendframework/zend-hydrator (Zend\Hydrator component for using HydratingResultSets)
samsonasik/error-hero-module suggests installing zendframework/zend-expressive-platesrenderer (^2.0 to be able to use plates template engine in zend-expressive ^3.0)
samsonasik/error-hero-module suggests installing zendframework/zend-expressive-twigrenderer (^2.0 to be able to use twig template engine in zend-expressive ^3.0)
samsonasik/error-hero-module suggests installing zendframework/zend-mvc-console (^1.1 for zend-mvc ^3.0 usage to be able to use Console Controller)
Writing lock file
Generating autoload files
ocramius/package-versions:  Generating version class...
ocramius/package-versions: ...done generating version class
  1. Copy config
cp vendor/samsonasik/error-hero-module/config/expressive-error-hero-module.local.php.dist config/autoload/expressive-error-hero-module.local.php
  1. Register ErrorHeroModule\Middleware\Expressive::class after ErrorHandler::class:
// config/pipeline.php
    $app->pipe(ErrorHandler::class);
    $app->pipe(ErrorHeroModule\Middleware\Expressive::class);
  1. Try "throw Exception()" at HomePageHandler middleware:
    public function handle(ServerRequestInterface $request) : ResponseInterface
    {
        throw new \Exception('test');
    }
  1. I got the error page correctly and recorded to DB:

screen shot 2018-07-03 at 10 43 04 pm
screen shot 2018-07-03 at 10 41 59 pm

If removing register of $app->pipe(ErrorHandler::class); works for you at your application, that's fine as far as it works.

@dennis-fedco
Copy link
Author

Thanks @samsonasik. I have updated my expressive-error-hero-module.local.php config file, and after some research I found the following.

First, I am guessing whatever I had in my config did not trigger the module (ErrorHeroModule), so instead ErrorHandler took over. Removing ErrorHandler left PHP's native error handling routines, which is what I was seeing.

Second, with ErrorHeroModule I saw that the SQL command being executed was:

INSERT INTO `log` (`date`, ... ) VALUES ('2018-07-03T20:03:18+00:00', ... );

Which gave error of:

ERROR 1292 (22007): Incorrect datetime value: '2018-07-03T20:03:18+00:00' for column 'date' at row 1

After fixing that, I see that:

  • The exception being thrown is written into the database log, as per the $config['log']['ErrorHeroModuleLogger']['writers'] option
  • but no explicit error was shown on the screen. Instead the generic message about the error is shown.

What I mean by explicit error, is PHP's native output and exactly what is being written to the log. i.e. :

Fatal error: Uncaught Exception: test in C:\Apache24\htdocs\portal\module\App\src\Handler\HomePageHandler.php:38
Stack trace: [30-some lines omitted]

I was expecting to see that level of detail rather than "We have encountered a problem..."
I suspect that it is the expected behavior, and that config data changed slightly from the version I used to use 2.1.3 to 2.12.0.

@samsonasik
Copy link
Owner

// config/autoload/error-hero-module.local.php
    'log' => [
        'ErrorHeroModuleLogger' => [
            'writers' => [

                [
                    'name' => 'db',
                    'options' => [
                        // ... current config
                        'formatter' => [
                             'name' => 'db',
                             'options' => [
                                  'dateTimeFormat' => 'Y-m-d H:i:s',
                             ],
                         ],
                      // ...
                    ],
                ],

            ],
        ],
    ],
  • For displaying error, you can set the 'display_errors' => 1, under display-settings config

@dennis-fedco
Copy link
Author

Thanks,

formatter is a useful setting. With the `display_errors it only shows the descriptive error in the error log via the writer.

Setting it to 1 goes back to showing my layout with this non-descriptive error message in browser:

Oops!
This is awkward.

We encountered a 500 Internal Server Error error.

setting display_errors to 0 shows this non-descriptive error in browser:

{
"type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html",
"title": "Internal Server Error",
"status": 500,
"detail": "We have encountered a problem and we can not fulfill your request. An error report has >been generated and sent to the support team and someone will attend to this problem urgently. Please >try again later. Thank you for your patience."
}

It only shows the descriptive error I was looking for in the database log. Is that the expected behavior?

@samsonasik
Copy link
Owner

Actually, removing : $app->pipe(ErrorHandler::class); line is fine as it will be overwritten in the $app->pipe(ErrorHeroModule\Middleware\Expressive::class);. I'm just not sure why it stop in that pipeline in your application as I tested it works at my side. If removing the $app->pipe(ErrorHandler::class); is works for you, that's fine then.

Yes, set the display_errors to 0 will use its configured default message, if you're not on ajax request/api request, it will uses template defined.

@dennis-fedco
Copy link
Author

I think it depends on the type of error. In my case I did not supply enough parameters to a method when the method expected a certain number of them.

With a different type of error, such as having raw output in a Handler, I do see the error messages on the screen. i.e:

EmitterException: Output has been emitted previously; cannot emit response i

Exact behavior probably depends on the type of error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants