Prerequisites
What happened?
Expected behavior:
ix-select's internal validation check should not produce an unhandled promise rejection when its internal isn't mounted.
Actual behavior:
In v5, HookValidationLifecycle calls host.getNativeInputElement() on ix-select from a fire-and-forget async callback with no .catch(). When it runs while the internal isn't mounted (right after connect, or during teardown), getNativeInputElement() rejects with Error: "Input element not found", which surfaces as an unhandled rejection.
Error: Input element not found
at Select.getNativeInputElement (ix-select.entry.js:946)
at checkIfRequiredFunction (validation-*.js:71)
(No parent frame — fired from a detached setTimeout.)
Steps to reproduce:
Render an ix-select that mounts asynchronously (e.g. ix-select-items added after an async data load).
Unmount or toggle it (e.g. disabled) shortly after.
See the uncaught Error: Input element not found in the console.
A synchronously-rendered ix-select does not reproduce it (the input ref exists before the timer fires).
Context (from published dist, v5.1.0)
The check is scheduled on a bare setTimeout in connectedCallback and not cleared in disconnectedCallback:
// dist/esm/validation-*.js
setTimeout(checkIfRequiredFunction); // no catch, not cleared on disconnect
So it can run when inputElement is null — before first render, or after teardown.
Possible directions
getNativeInputElement() could resolve null instead of rejecting (it's an internal check), and/or
checkIfRequiredFunction could .catch() it, and
disconnectedCallback could clearTimeout the scheduled check.
Impact / environment
Occurs at runtime (console noise) and fails test runners that treat unhandled rejections as failures (e.g. Vitest browser mode / Storybook interaction tests) even when assertions pass. Component: ix-select, @siemens/ix@5.1.0, Lit web components.
What type of frontend framework are you seeing the problem on?
JavaScript
On which version of the frontend framework are you experiencing the issue?
"lit": "^3.1.3"
Which version of iX do you use?
v5.1.0
Code to produce this issue.
<!doctype html>
<!--
Reduced test case: @siemens/ix@5.1.0 ix-select
Unhandled promise rejection "Input element not found" from
getNativeInputElement() during connect/teardown.
HOW TO RUN: open this file's URL over HTTP (e.g. a gist "raw" via
https://raw.githack.com, or `npx serve` locally). ES modules do not load
from a file:// path, so double-clicking will not work.
Then open the browser console, click the button, and wait ~1s.
Expected: a red "UNHANDLED REJECTION: Input element not found" appears.
-->
<html lang="en" data-ix-theme="classic-light" data-ix-color-schema="light">
<head>
<meta charset="UTF-8" />
<title>ix-select unhandled rejection repro</title>
<link
rel="stylesheet"
href="https://esm.sh/@siemens/ix@5.1.0/dist/siemens-ix/siemens-ix.css"
/>
</head>
<body>
<p>Open the console, click the button, then wait ~1s.</p>
<button id="toggle">Mount ix-select, then unmount after 300ms</button>
<div id="host"></div>
<script type="module">
import { defineCustomElements } from 'https://esm.sh/@siemens/ix@5.1.0/loader';
defineCustomElements();
// Make the unhandled rejection visible on-page and in the console.
addEventListener('unhandledrejection', (e) => {
const msg =
e.reason instanceof Error ? e.reason.message : String(e.reason);
console.error('UNHANDLED REJECTION:', msg, e.reason);
const pre = document.createElement('pre');
pre.style.color = 'red';
pre.textContent = 'UNHANDLED REJECTION: ' + msg;
document.body.appendChild(pre);
});
const host = document.getElementById('host');
document.getElementById('toggle').addEventListener('click', () => {
host.innerHTML = '';
// Mount an ix-select whose items arrive after an async tick, like a
// data-driven dropdown.
Promise.resolve().then(() => {
const select = document.createElement('ix-select');
select.setAttribute('required', '');
select.setAttribute('label', 'Example');
const item = document.createElement('ix-select-item');
item.setAttribute('label', 'Option A');
item.setAttribute('value', 'a');
select.appendChild(item);
host.appendChild(select);
// Remove it shortly after mount. The validation setTimeout scheduled
// in ix-select's connectedCallback then runs against a torn-down
// component whose internal <input> is gone -> getNativeInputElement()
// rejects, and nothing catches it.
setTimeout(() => {
host.innerHTML = '';
}, 300);
});
});
</script>
</body>
</html>
Prerequisites
What happened?
Expected behavior:
ix-select's internal validation check should not produce an unhandled promise rejection when its internal isn't mounted.
Actual behavior:
In v5, HookValidationLifecycle calls host.getNativeInputElement() on ix-select from a fire-and-forget async callback with no .catch(). When it runs while the internal isn't mounted (right after connect, or during teardown), getNativeInputElement() rejects with Error: "Input element not found", which surfaces as an unhandled rejection.
Error: Input element not found
(No parent frame — fired from a detached setTimeout.)
Steps to reproduce:
Render an ix-select that mounts asynchronously (e.g. ix-select-items added after an async data load).
Unmount or toggle it (e.g. disabled) shortly after.
See the uncaught Error: Input element not found in the console.
A synchronously-rendered ix-select does not reproduce it (the input ref exists before the timer fires).
Context (from published dist, v5.1.0)
The check is scheduled on a bare setTimeout in connectedCallback and not cleared in disconnectedCallback:
So it can run when inputElement is null — before first render, or after teardown.
Possible directions
getNativeInputElement() could resolve null instead of rejecting (it's an internal check), and/or
checkIfRequiredFunction could .catch() it, and
disconnectedCallback could clearTimeout the scheduled check.
Impact / environment
Occurs at runtime (console noise) and fails test runners that treat unhandled rejections as failures (e.g. Vitest browser mode / Storybook interaction tests) even when assertions pass. Component: ix-select, @siemens/ix@5.1.0, Lit web components.
What type of frontend framework are you seeing the problem on?
JavaScript
On which version of the frontend framework are you experiencing the issue?
"lit": "^3.1.3"
Which version of iX do you use?
v5.1.0
Code to produce this issue.