Found by the QA harness first sweep (PR #4283), reproducible on local dev with a connected wallet.
Affected routes
- /academy/avalanche-l1/native-token-bridge/01-erc20-to-native/07-bridge-tokens
- /academy/avalanche-l1/native-token-bridge/02-native-to-erc20/08-bridge-tokens
- /academy/avalanche-l1/native-token-bridge/03-native-to-native/07-bridge-native-tokens
Symptom
The embedded TestSend tool (components/toolbox/console/ictt/token-transfer/TestSend.tsx) crashes during hydration; the ToolboxMdxWrapper ErrorBoundary catches it and renders the "Try Again" fallback. The course exercise is unusable.
Console errors:
React has detected a change in the order of Hooks called by <component>.
The final argument passed to useCallback changed size between renders. Previous: [] Incoming: [[object Object], (arg)=>arg]
TypeError: Cannot read properties of undefined (reading 'length') at areHookInputsEqual
Suspected cause
Hook order is unstable across renders in TestSend. Two suspects:
getToolboxStore(destinationSelection.blockchainId)() at TestSend.tsx:85 — getToolboxStore (components/toolbox/stores/toolboxStore.ts:26) creates a new zustand store (with persist) on every call, and the hook it returns is invoked conditionally on a value that changes at runtime (empty string → selected chain id).
- Related:
getL1ListStore(...) calls inside useL1ByChainId follow the same dynamic-store-hook pattern.
TestSend is also not wrapped in withConsoleToolMetadata (no Container chrome, no requirements gating) — same for ChangeWeight (components/toolbox/console/permissioned-l1s/ChangeWeight.tsx). Worth fixing together for console consistency.
Repro
yarn dev
yarn e2e --grep "bridge-tokens"
# or open any affected route with a connected wallet and watch the embed area
Found by the QA harness first sweep (PR #4283), reproducible on local dev with a connected wallet.
Affected routes
Symptom
The embedded
TestSendtool (components/toolbox/console/ictt/token-transfer/TestSend.tsx) crashes during hydration; the ToolboxMdxWrapper ErrorBoundary catches it and renders the "Try Again" fallback. The course exercise is unusable.Console errors:
Suspected cause
Hook order is unstable across renders in
TestSend. Two suspects:getToolboxStore(destinationSelection.blockchainId)()at TestSend.tsx:85 —getToolboxStore(components/toolbox/stores/toolboxStore.ts:26) creates a new zustand store (withpersist) on every call, and the hook it returns is invoked conditionally on a value that changes at runtime (empty string → selected chain id).getL1ListStore(...)calls insideuseL1ByChainIdfollow the same dynamic-store-hook pattern.TestSendis also not wrapped inwithConsoleToolMetadata(no Container chrome, no requirements gating) — same forChangeWeight(components/toolbox/console/permissioned-l1s/ChangeWeight.tsx). Worth fixing together for console consistency.Repro