necolas/react-native-web · error · Error
Unrecognized signal `${signal}` or state `${curState}` for T
Error message
Unrecognized signal `${signal}` or state `${curState}` for Touchable responder `${responderID}` What it means
Touchable implements an explicit responder state machine; _receiveSignal looks up Transitions[curState][signal] to find the next state. If the (state, signal) pair has no defined transition, internal invariants are broken and it throws. This is almost always a library bug or an unbalanced responder event sequence, not user error.
Source
Thrown at packages/react-native-web/src/exports/Touchable/index.js:767
},
/**
* Receives a state machine signal, performs side effects of the transition
* and stores the new state. Validates the transition as well.
*
* @param {Signals} signal State machine signal.
* @throws Error if invalid state transition or unrecognized signal.
* @sideeffects
*/
_receiveSignal: function (signal: Signal, e: PressEvent) {
const responderID = this.state.touchable.responderID;
const curState = this.state.touchable.touchState;
const nextState = Transitions[curState] && Transitions[curState][signal];
if (!responderID && signal === Signals.RESPONDER_RELEASE) {
return;
}
if (!nextState) {
throw new Error(
'Unrecognized signal `' +
signal +
'` or state `' +
curState +
'` for Touchable responder `' +
responderID +
'`'
);
}
if (nextState === States.ERROR) {
throw new Error(
'Touchable cannot transition from `' +
curState +
'` to `' +
signal +
'` for responder `' +
responderID +
'`'View on GitHub (pinned to a9de220ba9)
Solutions
- Report the (signal, state, responderID) pair to react-native-web — likely a state-machine bug; include reproduction steps.
- Check for custom code that calls Touchable internals (responder callbacks) out of order.
- Verify no overlapping touch handling (nested Touchables/gesture layers) dispatches events on the same responder twice.
- Update react-native-web; the fix may already exist.
Example fix
// before touchable._receiveSignal(Signals.RESPONDER_RELEASE, id); // called without a grant // after // drive the responder only through real pointer events; remove manual signal dispatch
Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure responder events come only from real pointer handlers:
if (!isNativePointerEvent(event)) throw new Error('Do not dispatch Touchable signals manually'); Type guard
const hasValidTransition = (state, signal) => Boolean(Transitions[state] && Transitions[state][signal]);
Try / catch
try { touchable._receiveSignal(signal, id); } catch (e) { if (/Unrecognized signal/.test(e.message)) resetTouchableState(touchable); else throw e; } Prevention
- Never call Touchable internals; use pressable public props (onPressIn/out etc.)
- Keep react-native-web updated — state-machine races get patched
- Avoid overlapping/nested touch handlers on the same responder
When it happens
Trigger: Dispatching a touch signal (e.g. RESPONDER_RELEASE, RESPONDER_GRANT, RESPONDER_TERMINATE) while the Touchable is in a state with no registered transition for it — e.g. a release arriving in a state where it wasn't granted, or duplicate grant signals.
Common situations: Programmatically invoking internal responder methods; synthetic event sequences from nested/overlapping touchables or third-party gesture handling; edge cases during rapid taps where grant/release interleave unexpectedly.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Touchable cannot transition from `${curState}` to `${signal}
- Image: asset with ID "${source}" could not be found. Please
- The <Image> component cannot contain children. If you want t
- Invalid CSS keyframes type: ${typeof keyframesValue}
- StyleSheet.compose() only accepts 2 arguments, received ${le
AI-assisted analysis of necolas/react-native-web@a9de220ba9 (2026-09-01).
Data as JSON: /api/errors/545747fefcc2d3e5.
Report an issue: GitHub.