Describe the bug
Under sustained width-change pressure, UI5 throws
Uncaught Error: Web component processed too many times this task, max allowed is: 10
at o.process (RenderQueue.js:47)
The element on the call stack is one of ui5-multi-input, ui5-tokenizer, or ui5-input. After the throw, RenderQueue is in a poisoned state: subsequent reactive writes never flush, click events on UI5 elements stop firing, and the page must be reloaded.
Isolated Example
No response
Reproduction steps
Most reliably with FlexibleColumnLayout + a filter row containing a MultiInput whose tokenizer holds at least 2 tokens, but the underlying defect is independent of FCL — it is a same-task ResizeObserver feedback loop. Two reproductions:
Repro A — FCL separator drag
- Render a
FlexibleColumnLayout in TwoColumnsMidExpanded.
- Place a
MultiInput (or ValueHelpInput from libraries, which wraps MultiInput) inside the start column. Pre-populate it with ≥ 2 tokens.
- Drag the column separator quickly back and forth.
Stack trace:
RenderQueue.process @ RenderQueue.js:47
Render.js:51 (rAF callback)
UI5Element._invalidate
UI5Element setter (_inputWidth) ← Input.js:776 _handleResize
ResizeHandler tick
Repro B — Window resize at the desktop/tablet breakpoint
- Same setup as A.
- Resize the browser window back and forth across the ~1000 px boundary repeatedly.
Same error and same call stack.
Expected Behaviour
Should able to handle resize frequently at any level
Screenshots or Videos
No response
UI5 Web Components for React Version
~2.16.0
UI5 Web Components Version
~2.16.0
Browser
Chrome
Operating System
MacOS
Additional Context
Root cause (analysis)
The pattern is the same in Input._handleResize (line 776 of Input.js) and Tokenizer._handleResize (line 78 of Tokenizer.js):
// Input.js
_handleResize() {
this._inputWidth = this.offsetWidth;
}
// Tokenizer.js
_handleResize() {
this._nMoreCount = this.overflownTokens.length;
}
Each callback writes a width-derived value back into a reactive property. The reactive write triggers _invalidate, which queues the same component into RenderQueue. Within a single animation frame, ResizeObserver can deliver multiple entries for the same element; combined with cascaded width changes from sibling elements that each queue further invalidations, the same component is processed > 10 times in one task. RenderQueue's MAX_PROCESS_COUNT = 10 limit then trips.
Specifically:
- ResizeObserver tick →
_handleResize writes reactive prop.
- The reactive write triggers
_invalidate → component is queued for the next render pass.
- Next render lays out the page, which can change width of sibling components (FCL animation, MultiInput overflow recalculation propagates token list width to the hosting Input).
- Sibling ResizeObservers fire in the same task → goto 1.
- After 10 passes RenderQueue throws.
The 10-pass ceiling is correct as a runaway guard, but the components themselves do not protect against feeding their own ResizeObserver. The _handleResize body should:
- Skip the write if the observed dimension has not changed since the last commit, or
- RAF-coalesce so multiple ticks within one animation frame collapse to one write.
A workaround we deployed at the application layer:
// Patch _handleResize on every ui5-multi-input / ui5-tokenizer / ui5-input
// inside our filter row so the reactive write is RAF-throttled and
// suppressed when width is unchanged.
function patchOne(el) {
const original = el._handleResize;
let pending = null;
let lastWidth;
el._handleResize = function () {
const width = this.offsetWidth;
if (width === lastWidth) return;
if (pending !== null) return;
pending = requestAnimationFrame(() => {
pending = null;
const next = this.offsetWidth;
if (next === lastWidth) return;
lastWidth = next;
original.call(this);
});
};
}
This eliminates the loop without changing behaviour. The patch is a hack — fixing it inside UI5 itself is the right place.
Suggested fix
Inside Input._handleResize and Tokenizer._handleResize:
_handleResize() {
const w = this.offsetWidth;
if (w === this._lastObservedWidth) return;
this._lastObservedWidth = w;
this._inputWidth = w; // or _nMoreCount = this.overflownTokens.length;
}
Even better, RAF-coalesce so successive ticks within one frame produce at most one reactive write.
Why this matters
Any application that places MultiInput (directly or through ValueHelpInput) in a FlexibleColumnLayout start column is vulnerable. The bug is data-dependent (token count) and timing-dependent (sustained resize), so it does not show up in unit tests but is reliably hit in production by users dragging the separator or resizing the window. Once thrown, the entire page must be reloaded.
Relevant log output
Organization
No response
Declaration
Describe the bug
Under sustained width-change pressure, UI5 throws
The element on the call stack is one of
ui5-multi-input,ui5-tokenizer, orui5-input. After the throw, RenderQueue is in a poisoned state: subsequent reactive writes never flush, click events on UI5 elements stop firing, and the page must be reloaded.Isolated Example
No response
Reproduction steps
Most reliably with
FlexibleColumnLayout+ a filter row containing aMultiInputwhose tokenizer holds at least 2 tokens, but the underlying defect is independent of FCL — it is a same-task ResizeObserver feedback loop. Two reproductions:Repro A — FCL separator drag
FlexibleColumnLayoutinTwoColumnsMidExpanded.MultiInput(orValueHelpInputfrom libraries, which wrapsMultiInput) inside the start column. Pre-populate it with ≥ 2 tokens.Stack trace:
Repro B — Window resize at the desktop/tablet breakpoint
Same error and same call stack.
Expected Behaviour
Should able to handle resize frequently at any level
Screenshots or Videos
No response
UI5 Web Components for React Version
~2.16.0
UI5 Web Components Version
~2.16.0
Browser
Chrome
Operating System
MacOS
Additional Context
Root cause (analysis)
The pattern is the same in
Input._handleResize(line 776 ofInput.js) andTokenizer._handleResize(line 78 ofTokenizer.js):Each callback writes a width-derived value back into a reactive property. The reactive write triggers
_invalidate, which queues the same component into RenderQueue. Within a single animation frame, ResizeObserver can deliver multiple entries for the same element; combined with cascaded width changes from sibling elements that each queue further invalidations, the same component is processed > 10 times in one task. RenderQueue'sMAX_PROCESS_COUNT = 10limit then trips.Specifically:
_handleResizewrites reactive prop._invalidate→ component is queued for the next render pass.The 10-pass ceiling is correct as a runaway guard, but the components themselves do not protect against feeding their own ResizeObserver. The
_handleResizebody should:A workaround we deployed at the application layer:
This eliminates the loop without changing behaviour. The patch is a hack — fixing it inside UI5 itself is the right place.
Suggested fix
Inside
Input._handleResizeandTokenizer._handleResize:Even better, RAF-coalesce so successive ticks within one frame produce at most one reactive write.
Why this matters
Any application that places
MultiInput(directly or throughValueHelpInput) in aFlexibleColumnLayoutstart column is vulnerable. The bug is data-dependent (token count) and timing-dependent (sustained resize), so it does not show up in unit tests but is reliably hit in production by users dragging the separator or resizing the window. Once thrown, the entire page must be reloaded.Relevant log output
Organization
No response
Declaration