A component used by a native screen renders its template, but anything its own <script client> declares is undefined at runtime. No diagnostic, no runtime error — the bindings just quietly do nothing.
Measured
resources/components/PhoneMessagesButton.stx, drawn by two native screens, with three probes added to its template:
<Text :text="'hello'" /> → "hello"
<Text :text="String(session.signedIn())" /> → "true" (the screen's scope: fine)
<Text :text="String(typeof pmbUnread)" /> → "undefined" (the component's own script)where the component holds:
<script client>
const pmbUnread = derived(() => Number(session.profile()?.messagesUnread) || 0)
const pmbLabel = derived(() => nav[session.locale()].phone.messages)
</script>So the template is compiled and the screen's scope reaches it, but the component's script never runs. <script client lang="ts"> behaves the same.
Why it is worth a diagnostic
Both of this component's bindings were dead for weeks without anyone noticing, because the two failure modes are invisible:
:if="pmbUnread > 0"withpmbUnreadundefined is simply false, so the element is never drawn. Nothing is logged; the screen looks fine, one feature is just missing.:accessibilityLabel="pmbLabel"becomes no label at all, which only a screen-reader user finds.
Meanwhile @click="session.open('/m/messages')" kept working, because event handlers run in the screen's scope — so the component looked alive.
An "identifier not in scope" diagnostic from stx native compile would have caught both at build time; the compiler already reports unmapped and unread-event diagnostics, which is the same shape of check.
If dropping component scripts is deliberate for the native renderer, the diagnostic is still the fix: it should be an error to reference a name the compiled output cannot resolve, rather than a binding that evaluates to undefined.
Worked around by moving the component's state into the screens it is drawn in, so the template reads only the screen's scope. Measured on stx 0.2.530, Craft 0.0.187, Bun 1.4.3-canary.1.