Skip to content

[BUGFIX] Survive a null or unknown code language - #18

Open
davidsteeb wants to merge 2 commits into
masterfrom
bugfix/null-code-language
Open

davidsteeb wants to merge 2 commits into
masterfrom
bugfix/null-code-language

Conversation

@davidsteeb

@davidsteeb davidsteeb commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

A stored code_language value can take the whole page down with a 500, in two ways.

A null language

code_language is declared as code_language text in ext_tables.sql, so the column is nullable. The TCA field has default => '', but a record can still end up with NULL, and the branch did not survive it:

if (!($processedData['data']['code_language'] ?? true)) {
    // autodetect
} else {
    $highlighted = $highlight->highlight($processedData['data']['code_language'], …);
}

?? substitutes only for NULL, so it yields true, the falsy check reads that as "a language was chosen", and NULL goes straight to the highlighter. What happens next depends on the PHP version, but the page dies either way:

PHP result
8.4 DomainException: Unknown language: "" from Highlighter::highlight()
8.5 Using null as an array offset is deprecated in Highlighter::getLanguage(), turned into an exception by TYPO3's error handler

Normalising the value to a string before deciding puts NULL on the autodetect branch, exactly where an empty string already goes.

A language that no longer resolves

highlight() throws DomainException when the name is not registered, and nothing caught it. A record can stop resolving without ever being edited — the language may be dropped from the registered set, or the record may arrive from an installation that had it. Same outcome as above: a stored value ends the request.

That one exception is now caught and the language detected instead. A language that does resolve is still used as it was, so this is not a blanket catch.

Verified

Against a TYPO3 v14 site on PHP 8.5, one content element, only code_language varied:

code_language before after
NULL HTTP 500 HTTP 200, detected
'' HTTP 200 HTTP 200, detected
'klingonisch' (not registered) HTTP 500 HTTP 200, detected
'bash' HTTP 200 HTTP 200, still bash

The last row is the one that matters for the catch: a language that resolves is untouched. Elements that already carried a valid language render exactly as before, and the recovered elements produce the regular markup with an hljs class on the detected language.

code_language is a nullable column, so a record can hold NULL where the
TCA default would have written an empty string. "??" substitutes only for
NULL, so the falsy check read that NULL as "a language was chosen" and
passed it to the highlighter.

There it ends the request: on PHP 8.4 highlight() throws
DomainException: Unknown language: "", and on 8.5 the lookup trips
"Using null as an array offset" first, which TYPO3 turns into an
exception. Either way the page returns a 500.

Normalise the value to a string before deciding, so NULL takes the
autodetect branch like an empty string does.
highlight() throws DomainException when the given language is not
registered, and nothing caught it, so a stored value that no longer
resolves ended the request with a 500 - the same failure as a null
language, just from the other direction.

A language can stop resolving without the record changing: it may be
dropped from the registered set, or the record may arrive from an
installation that had it. Catch that one exception and detect the
language instead. A language that does resolve is still used as it was.
@davidsteeb davidsteeb changed the title [BUGFIX] Treat a null code language as autodetect [BUGFIX] Survive a null or unknown code language Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants