General Tips

Typo3 Debug Mode

Manual to always display Exceptions and Errors in the backend and frontend of Typo3:

Typo3: Debugging and Development Setup

Errors

  • Does the error happens on every page or only on a specific one?

  • Does the error happens on every form or only on a specific one?

Tips:

  • On general errors:

    • Always check the Javascript console of your browser, see Javascript problem.

    • Always check the Webserver log files.

Procedure to Find an Irreproducible Error

  • Find out the date and time on which the error occurred as precisely as possible

  • Find out the user-name of the person who experienced the error

  • Search the logs at the time of the Error:

    • qfq.log

      • location: fileadmin/protected/qfqProject/log/qfq.log

        • NOTE: The log directory has been moved into qfqProject with a recent upgrade of QFQ. For backwards compatibility logs are still stored in fileadmin/protected/log/ if that directory already exists.

      • Look for error messages which were sent to the user at that time. (search for user-name in file)

      • Look at actions performed during the time of Error

    • FormSubmitLog

      • location: table named ‘FormSubmitLog’ in the qfq database

      • In the SQL Table FormSubmitLog search the column FEUser for the user-name

      • does the data (in the column formData) submitted at the time of the error coincide with the data saved in the database?

    • sql.log

      • location: fileadmin/protected/qfqProject/log/sql.log

      • search for the form that was active when the error occurred:

        • e.g.: If the form is named ‘requestGreview’ search for ‘form:requestGreview’

Typo3

Caching

Content, generated by QFQ, is generally not cached. But the QFQ content records are cached by Typo3. This means if there is a content element ‘Insert Records’ on a page ‘A’ which includes a QFQ record from page ‘B’ and such QFQ record is modified (the SQL definition, not the delivered output), the new definition becomes by default only visible if the cached is cleared.

To simplify the situation, set on the page of the QFQ record (B) in Page TS Config:

TCEMAIN.clearCacheCmd = pages

Develop environment

  • For nginx, set in php-fpm location TYPO3_CONTEXT:

    location ~ \.php(/|$) {
                    fastcgi_pass unix:/run/php/php-fpm.sock;
                    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                    include snippets/fastcgi-php.conf;
                    fastcgi_param TYPO3_CONTEXT "Development";
     }
    

Backend > Settings: Password

  • This can be disabled (do it only on develop instances for security reasons) if the TYPO3_CONTEXT “Development” is

given (see above).

Caching Apache

Apache headers should be enabled. Otherwise you might encounter effcts like saving a form does not show automatically the latest version:

a2enmod headers

QFQ specific

Checklist wkhtml problems

  • config.baseUrl is configured and correct.

  • To track down problems:

    • In Configuration set debug.showDebugInfo=auto,download.

    • Do the download.

    • Check Debug for any output.

    • Grab the URL given in the Debug, open a browser in private mode (no existing browser session) and open the URL.

    • Check the –cookie-jar ‘/tmp/qfq.cookie….’ file for the cookie.

    • Call wkhtml manually on the webserver, with the same options as given in the Debug.

A variable {{<var>}} is empty

The sanitize rule is violated and therefore the value has been removed. Set {{<var>:<store>:all}} as a test.

Page is white: no HTML code at all

This should not happen.

The PHP process stopped at all. Check the Apache error logfile, look for a stacktrace to find the latest function. Send a bug report.

Problem with query or variables

Specify the required sanitize class. Remember: for STORE_FORM and STORE_CLIENT the default is sanitize class is digit. This means if the variable content is a string, this violates the sanitize class and the variable will not be replaced.

Tip on Form: put the problematic variable or SQL statement in the ‘title’ or note ‘field’ of a FormElement. This should show the content. For SQL statements, remove the outer token (e.g. only one curly brace) to avoid triggering SQL:

FE.title: Person { SELECT ... WHERE id={{buggyVar:alnumx}} }

Tip on Report: In case the query did not contain any double ticks, just wrap all but ‘SELECT’ in double ticks:

Buggy query:  sql = SELECT id, ... FROM MyTable WHERE status={{myVar}} ORDER BY status
Debug query:  sql = SELECT "id, ... FROM MyTable WHERE status={{myVar}} ORDER BY status"

Error read file qfq.json: syntax error on line xx

Check the given line number. If it’s an SQL statement, enclose it in single or double ticks.

Output a text, substitute embedded QFQ variables

The content will be copied to ‘_text’. In 10.tail than the ‘{{text:R}}’ will be substituted with all known variables. Note the ‘-’ in ‘{{text:RE::-}}’, this will prevent that QFQ escapes any character from the content.

{
  sql = SELECT no.text AS _text
           FROM Note AS no
           WHERE id=...
  tail = {{text:RE::-}}
}

TypeAhead list with T3 page slug names - use of the T3 DB

To define a typeahead list of T3 page slug names:

FE.type = text
FE.parameter.typeAheadSql = SELECT p.slug FROM {{dbNameT3:Y}}.Pages AS p WHERE p.deleted=0 AND p.slug!='' AND p.slug LIKE ? ORDER BY p.slug LIMIT 20
FE.parameter.typeAheadMinLength = 1

Set FE-User password

To offer an FE User the possibility to change the own T3 FE password, create a form:

f.name = changeFePassword
f.title = Change Password
f.table = Person   (QFQ Table, not T3)
f.permitNew = never
f.permitEdit = sip

fe[1].name = myPassword
fe[1].title = Password
fe[1].class = native
fe[1].type = password
fe[1].mode = required
fe[1].parameter = retype

fe[2].class = action
fe[2].type = afterSave
fe[2].parameter = sqlAfter={{UPDATE {{dbNameT3:Y}}.fe_users SET password='{{myPassword:FE:all:p}}' WHERE username='{{feUser:T}}' AND deleted=0

Call the form via SIP on an existing record. Often QFQ has an own table for persons and also the current user exist in T3 fe_users table.

Child record created but not assigned to parent

Typically the reference id to the parent record is missing. Check sql.log to see the final SQL statement.

Logging

General webserver error log

For apache: /var/log/apache2/error_log

Especially if you got a blank page (no rendering at all), this is typically an uncaught PHP error. Check the error message and report the bug (https://qfq.io > Contact).

Call to undefined function qfq\mb_internal_encoding()

Check that all required php modules are installed. See Preparation.

Error Messages

Internal Server Error

The browser shows a red popup with ‘Internal Server Error’. The message is generated in the browser. Happens e.g. an AJAX request response of QFQ (=Server) is broken. This might happen e.g. if PHP can’t start successfully or PHP fails to run due to a missing php module or broken configuration.

Oops, an error occurred! Code: 20180612205917761fc593

You see this message on all places where a QFQ content record should produce some output. Typically the extension fails to load. If the error message disappears when the QFQ extension is disabled (instead a message qfq_qfq can’t be rendered is shown), than QFQ is the problem.

Search the given code in typo3temp/logs/*, in this example 20180612205917761fc593. You’ll should find a stacktrace with a more detailed message.

The error might occur if there are problematic characters in qfq.json, like single or double ticks inside strings, wich are not enclosed (correctly).

Further T3 Logfile

  • /var/www/html/typo3temp/var/log/…

sendEmail: Error => TLS setup failed

Switch off the TLS encryption. In Configuration specify for config.sendEMailOptions:

-o tls=no

sendEmail: ‘random’ injected spaces

If in emails unwanted spaces appear, please check that the body does not contain lines longer than 1000 characters. The spaces will be inserted by the email system in such long lines and has nothing to do with QFQ.

In HTML mails, this situation might happen if all newlines will be replaced by <br>. To prevent this situation, QFQ will check for <br> (without newline) and add automatically a newline behind it. This applies only to email body texts.

Javascript problem

Open the ‘Webdeveloper Tools’ (FF: F12, Chrome/Opera: Right mouse click > Inspect Element) in your browser, switch to ‘console’ and reload the page. Inspect the messages.

TinyMCE

Glyph Icons in ‘<span>’

TinyMCE forbids by default HTML tag ‘span’ with ‘class’ attribute. E.g.:

<span class="glyphicon glyphicon-user"></span>

To allow it, add ‘span’ to the valid elements in the FormElement.parameter field:

editor-extended_valid_elements = span[class|style]

The HTML span tag has to be added via ‘source’ view. At least in TinyMCE 4.7.13, the glyph is still not shown in the editor.

FE User

The FE User record (table: fe_users)

  • Has to exist.

  • Has to be assigned to at least one FE Group. Check fe_users.usergroup.

  • Has to be assigned to a T3 page fe_users.pid.

  • The T3 page has to be configured as record store on the T3 Plugin login box.

  • Access time has to be zero or a currently valid period.

MariaDB

Row size too large

  • Details: https://mariadb.com/kb/en/troubleshooting-row-size-too-large-errors-with-innodb/

  • Typically too many columns per table on an InnoDB Table.

  • First try is to check (and to change) ROW_FORMAT:

    ALTER TABLE tab ROW_FORMAT=DYNAMIC;
    
  • Bad workaround for creating a wide table:

    SET SESSION innodb_strict_mode=OFF;
    CREATE TABLE ...
    
  • Best is to change as much columns as neccessary from varchar() to tinytext / text

SQL Dump with one record per line

Sometimes it’s helpful to have SQL dumps with each record on a single line:

msyqldump --skip-opt <DB-Name>

Difference column type ‘timestamp’ & ‘dateime’

In MariaDB, both TIMESTAMP and DATETIME store date and time values, but they behave quite differently under the hood. Here’s the real distinction:

  • Time zone handling (biggest difference)

    • TIMESTAMP: Stored internally in UTC and automatically converted to the session’s time zone when retrieved.

    • DATETIME: Stored exactly as given, with no time zone conversion at all.

    👉 This means if your server or users operate across time zones, TIMESTAMP will shift values depending on the session time zone, while DATETIME will not.

  • Range of values

    • TIMESTAMP: Limited range — roughly 1970-01-01 to 2038-01-19 (because of Unix time limits).

    • DATETIME: Much wider range — from 1000-01-01 to 9999-12-31.

  • Storage size

    • TIMESTAMP: Typically 4 bytes (more compact).

    • DATETIME: Typically 8 bytes.

  • Automatic initialization / updates

    • TIMESTAMP: Can automatically set itself to the current time (CURRENT_TIMESTAMP) on insert/update (commonly used for audit columns like created_at, updated_at).

    • DATETIME: Can also do this in modern MariaDB, but historically it was less automatic.

  • Use cases

    • Use TIMESTAMP when:

      • You care about absolute points in time (e.g., logs, events)

      • You want automatic timezone handling

    • Use DATETIME when:

      • You need a fixed date/time value that should never shift (e.g., a meeting scheduled at “2026-05-01 10:00” local time)

      • You need a wider date range

PHP

php-fpm timeout

Default timeout is 60s. To extend:

# --- PHP Processing ---
location ~ \.php($|/) {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php-fpm.sock; # Adjust to your PHP version

    fastcgi_read_timeout 300;
    fastcgi_send_timeout 300;

    # Security: Header settings from .htaccess
    add_header X-Content-Type-Options "nosniff";
    add_header X-UA-Compatible "IE=edge";
}

timezone

  • PHP recommends to explicitly set the timezone in php.in.

  • Before Ubuntu 24.04/php8.3, the php package was configured to use system timezone if it is not set explicitly.

  • php.ini:

    date.timezone = Europe/Zurich