This issue has been created
There is 1 update.
 
 
XWiki Platform / cid:jira-generated-image-avatar-290e2590-a800-48ad-8218-50cfbafedd37 XWIKI-24700 Open

A failed translations request never resolves the xwiki-l10n RequireJS module, blocking all dependent modules

 
View issue   ·   Add comment
 

Issue created

 
cid:jira-generated-image-avatar-8cb451ca-a1e9-414f-a627-32abad2e9559 Vincent Massol created this issue on 14/Aug/26 12:40
 
Summary: A failed translations request never resolves the xwiki-l10n RequireJS module, blocking all dependent modules
Issue Type: cid:jira-generated-image-avatar-290e2590-a800-48ad-8218-50cfbafedd37 Bug
Affects Versions: 18.3.0
Assignee: Unassigned
Components: Node - Translation
Created: 14/Aug/26 12:40
Priority: cid:jira-generated-image-static-major-483e1e37-5366-4176-91e6-c95431581d89 Major
Reporter: Vincent Massol
Description:

Problem

When the localization REST endpoint fails to return usable JSON, the xwiki-l10n RequireJS loader plugin never resolves its module. Every JavaScript module that declares a xwiki-l10n!... dependency is therefore blocked forever instead of degrading to untranslated keys, so the feature it implements silently never initialises.

Steps to reproduce

  1. Make /xwiki/rest/wikis/<wiki>/localization/translations return something other than the expected JSON — an HTTP error, a network failure, or an HTML error page injected by a reverse proxy / CDN in front of XWiki.
  2. Load any page whose JavaScript depends on translations through the xwiki-l10n! loader plugin — for example any page containing a Live Data.

Actual behaviour

The browser console reports, once per query:

Failed to retrieve the translations for query [...]
SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
An issue occurred during the resolution of localization query [object Object]

and the dependent modules never finish loading. A Live Data, for instance, renders the raw translation keys (livedata.pagination.currentEntries, livedata.filter.list.emptyLabel, ...) and no entries at all.

Cause

In xwiki-platform-localization-webjar/src/main/node/src/l10n.ts, the loader's resolve() rejection handler logs the error but never calls onLoad:

.catch((err: unknown) => {
  console.error(
    `An issue occurred during the resolution of localization query ${query}`,
    err,
  );
});

RequireJS waits for onLoad to be called before considering the module loaded, so the promise rejection turns into a permanently pending module.

Two smaller problems are visible in the same handler:

  • ${query} interpolates the query object, producing the useless [object Object] in the message. It should be serialised.
  • The rejection observed in practice is a TypeError: Cannot read properties of undefined (reading 'escapeHTML') rather than the underlying JSON parse error, which suggests the error is being mangled on the way out of the resolver and makes diagnosis harder.

Expected behaviour

A failed translation resolution should degrade gracefully rather than break the page: onLoad should still be called — with the untranslated keys, or with an empty map whose get() returns null — so that dependent modules initialise and merely display untranslated labels. The error should stay logged, and the logged message should identify the failing query.

How this was found

Observed on xwiki.org, where Cloudflare currently answers every /xwiki/rest/** request with a managed-challenge HTML page (403, cf-mitigated: challenge). That Cloudflare rule is a separate, infrastructure-side problem, but it exposed the fact that XWiki has no graceful fallback: instead of a page with untranslated labels, every page containing a Live Data is left non-functional.

 
 

1 update

 
cid:jira-generated-image-avatar-8cb451ca-a1e9-414f-a627-32abad2e9559 Changes by Vincent Massol on 14/Aug/26 12:40
 
Description: h2. Problem

When the localization REST endpoint fails to return usable JSON, the {{xwiki \ -l10n}} RequireJS loader plugin never resolves its module. Every JavaScript module that declares a {{xwiki \ -l10n \ ! ... }} dependency is therefore blocked forever instead of degrading to untranslated keys, so the feature it implements silently never initialises.

h2. Steps to reproduce

# Make {{/xwiki/rest/wikis/<wiki>/localization/translations}} return something other than the expected JSON — an HTTP error, a network failure, or an HTML error page injected by a reverse proxy / CDN in front of XWiki.
# Load any page whose JavaScript depends on translations through the {{xwiki
\ -l10n \ !}} loader plugin — for example any page containing a Live Data.

h2. Actual behaviour

The browser console reports, once per query:

{
code noformat }
Failed to retrieve the translations for query [...]
SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
An issue occurred during the resolution of localization query [object Object]
{
code noformat }

and the dependent modules never finish loading. A Live Data, for instance, renders the raw translation keys
\ ({{livedata.pagination.currentEntries}}, {{livedata.filter.list.emptyLabel}}, ... \ ) and no entries at all.

h2. Cause

In {{xwiki \ -platform \ -localization \ -webjar/src/main/node/src/l10n.ts}}, the loader's rejection handler for {{ resolver. resolve \(\) }} rejection handler logs the error but never calls {{onLoad}}:

{code:language=typescript}
.catch((err: unknown) => {
  console.error(
    `An issue occurred during the resolution of localization query ${query}`,
    err,
  );
});
{code}

RequireJS waits for {{onLoad}} to be called before considering the module loaded, so the promise rejection turns into a permanently pending module.

Two smaller problems are visible in the same handler:

*
{{${query}}} The template literal interpolates the query object directly , producing so the logged message ends with a useless {{ \ [object Object \ ]}} in instead of naming the message keys that failed . It should be serialised.
* The rejection observed in practice is a {{TypeError: Cannot read properties of undefined
\ (reading 'escapeHTML' \ )}} rather than the underlying JSON parse error, which suggests the error is being mangled on the its way out of the resolver and makes diagnosis harder.

h2. Expected behaviour

A failed translation resolution should degrade gracefully rather than break the page: {{onLoad}} should still be called — with the untranslated keys, or with an empty map whose {{get \(\) }} returns {{null}} — so that dependent modules initialise and merely display untranslated labels. The error should stay logged, and the logged message should identify the failing query.

h2. How this was found

Observed on xwiki.org, where Cloudflare currently answers every request under {{/xwiki/rest/ \*\* }} request with a managed \ -challenge HTML page \ ({{403}} , with a {{cf \ -mitigated: challenge}} \ header ). That Cloudflare rule is a separate, infrastructure \ -side problem, but it exposed the fact that XWiki has no graceful fallback: instead of a page with untranslated labels, every page containing a Live Data is left non \ -functional.