Troubleshooting

Nette Is Not Working, White Page Is Displayed

  • Try putting ini_set('display_errors', '1'); error_reporting(E_ALL); after declare(strict_types=1); in the index.php file to force the display of errors
  • If you still see a white screen, there is probably an error in the server setup and you will discover the reason in the server log. To be sure, check if PHP is working at all by trying to print something using echo 'test';.
  • If you see an error Server Error: We're sorry! …, continue with the next section:

Error 500 Server Error: We're sorry! …

This error page is displayed by Nette in production mode. If you are seeing it on a developer machine, switch to developer mode.

If the error message contains Tracy is unable to log error, find out why the errors cannot be logged. You can do this by, for example, switching to developer mode and calling Tracy\Debugger::log('hello'); after $configurator->enableTracy(...). Tracy will tell you why it can't log. The cause is usually insufficient permissions to write to the log/ directory.

If the sentence Tracy is unable to log error is not in the error message (anymore), you can find out the reason for the error in the log in the log/ directory.

One of the most common reasons is an outdated cache. While Nette cleverly automatically updates the cache in development mode, in production mode it focuses on maximizing performance, and clearing the cache after each code modification is up to you. Try to delete temp/cache.

Error #[\ReturnTypeWillChange] attribute should be used

This error occurs if you have upgraded PHP to version 8.1 but are using Nette, which is not compatible with it. So the solution is to update Nette to a newer version using composer update. Nette has supported PHP 8.1 since version 3.0. If you are using an older version (you can find out by looking in composer.json), upgrade Nette or stay with PHP 8.0.

Setting Directory Permissions

If you're developing on macOS or Linux (or any other Unix based system), you need to configure write privileges to the web server. Assuming your application is located in the default directory /var/www/html (Fedora, CentOS, RHEL)

cd /var/www/html/MY_PROJECT
chmod -R a+rw temp log

On some Linux systems (Fedora, CentOS, …) SELinux may be enabled by default. You may need to update SELinux policies, or set paths of temp and log directories with correct SELinux security context. Directories temp and log should be set to httpd_sys_rw_content_t context; for the rest of the application – mainly app folder – httpd_sys_content_t context will be enough. Run on the server as root:

semanage fcontext -at httpd_sys_rw_content_t '/var/www/html/MY_PROJECT/log(/.*)?'
semanage fcontext -at httpd_sys_rw_content_t '/var/www/html/MY_PROJECT/temp(/.*)?'
restorecon -Rv /var/www/html/MY_PROJECT/

Next, the SELinux boolean httpd_can_network_connect_db needs to be enabled to permit Nette to connect to the database over network. By default, it is disabled. The command setsebool can be used to perform this task, and if the option -P is specified, this setting will be persistent across reboots.

setsebool -P httpd_can_network_connect_db on

How to Change or Remove www Directory from URL?

The www/ directory used in the sample projects in Nette is the so-called public directory or document-root of the project. It is the only directory whose contents are accessible to the browser. And it contains the index.php file, the entry point that starts a web application written in Nette.

To run the application on the hosting, you need to set the document-root to this directory in the hosting configuration. Or, if the hosting has a pre-made folder for the public directory with a different name (for example web, public_html etc.), simply rename www/.

The solution isn't to “get rid” of the www/ folder using rules in the .htaccess file or in the router. If the hosting would not allow you to set document-root to a subdirectory (i.e. create directories one level above the public directory), look for another. You would otherwise be taking a significant security risk. It would be like living in an apartment where you can't close the front door and it's always wide open.

How to Configure a Server for Nice URLs?

Apache: extension mod_rewrite must be allowed and configured in a .htaccess file.

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(pdf|js|ico|gif|jpg|png|css|rar|zip|tar\.gz)$ index.php [L]

To alter Apache configuration with .htaccess files, the AllowOverride directive has to be enabled. This is the default behavior for Apache.

nginx: the try_files directive should be used in server configuration:

location / {
	try_files $uri $uri/ /index.php$is_args$args;  # $is_args$args is important
}

Block location must be defined exactly once for each filesystem path in server block. If you already have a location / block in your configuration, add the try_files directive into the existing block.

Nette generates links with the same protocol as the current page is using. So on the https://foo page, it generates links starting with https: and vice versa. If you're behind an HTTPS-stripping reverse proxy (for example, in Docker), then you need to set up a proxy in configuration to make the protocol detection work properly.

If you use Nginx as a proxy, you need to have redirection set up like this:

location / {
	proxy_set_header Host $host;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	proxy_set_header X-Forwarded-Proto $scheme;
	proxy_set_header X-Forwarded-Port  $server_port;
	proxy_pass http://IP-aplikace:80;  # IP or hostname of the server/container where the application is running
}

Next, you need to specify the IP proxy and, if applicable, the IP range of your local network where you run the infrastructure:

http:
	proxy: IP-proxy/IP-range

Use of Characters { } in JavaScript

Characters { and } are used for writing Latte tags. Everything (except space and quotation mark) following the { character is considered a tag. If you need to print character { (often in JavaScript), you can put a space (or other empty character) right after {. By this you avoid interpreting it as a tag.

If it's necessary to print these characters in a situation where they would be interpreted as a tag you can use specials tags to print out these characters – {l} for { and {r} for }.

{is tag}
{ is not tag }
{l}is not tag{r}

Notice Presenter::getContext() is deprecated

Nette is by far the first PHP framework that switched to dependency injection and led programmers to use it consistently, starting from the presenters. If a presenter needs a dependency, it will ask for it. In contrast, the way we pass the entire DI container to a class and it pulls the dependencies from it directly is considered an antipattern (it's called a service locator). This way was used in Nette 0.x before the advent of dependency injection, and its relic is the method Presenter::getContext(), long ago marked as deprecated.

If you port a very old Nette application, you may find that it still uses this method. So since version 3.1 of nette/application you will encounter the warning Nette\Application\UI\Presenter::getContext() is deprecated, use dependency injection, since version 4.0 you will encounter the error that the method does not exist.

The clean solution, of course, is to redesign the application to pass dependencies using dependency injection. As a workaround, you can add your own getContext() method to your base presenter and bypass the message:

abstract BasePresenter extends Nette\Application\UI\Presenter
{
	private Nette\DI\Container $context;

	public function injectContext(Nette\DI\Container $context)
	{
		$this->context = $context;
	}

	public function getContext(): Nette\DI\Container
	{
		return $this->context;
	}
}
version: 4.0