redis/node-redis · error · Error
[Proxy] Failed to send SMIGRATED notification: ${migratedRes
Error message
[Proxy] Failed to send SMIGRATED notification: ${migratedResult.error} What it means
Thrown by the proxied fault injector during the second phase of a simulated cluster slot migration: after the SMIGRATING push notification was sent and the 2-second maintenance delay elapsed, the proxy failed to deliver the SMIGRATED notification to the source node's client connection. The interpolated migratedResult.error carries the proxy server's own failure reason (a SendResult with success=false).
Source
Thrown at packages/test-utils/lib/fault-injector/proxied-fault-injector-cluster.ts:142
if (!destinationNode) {
throw new Error(`[Proxy] No destination node`);
}
const sMigratedNotification = buildSMigratedNotification([
{
targetNode: destinationNode,
slotRanges: slots,
},
]);
const migratedResult = await this.proxyController.sendToClient(
connections[sourceNode.id][0],
sMigratedNotification
);
if (!migratedResult.success) {
throw new Error(
`[Proxy] Failed to send SMIGRATED notification: ${migratedResult.error}`
);
}
return {
status: "success",
error: null,
output: "Migration completed!",
};
}
}
interface ProxyNode {
id: string;
host: string;
port: number;
proxyPort: number;
}View on GitHub (pinned to 90fd0652bc)
Solutions
- Confirm the proxy server is still running and reachable (proxyController.getStats()) before triggering the migrate action.
- Ensure the cluster client stays connected across the 2-second maintenance delay — do not tear down or reconnect the client mid-migration.
- Re-resolve the live connection id immediately before the SMIGRATED send: call proxyController.getConnections() and re-read connections[sourceNode.id][0] rather than reusing the id captured before the 2s wait.
- Inspect the interpolated migratedResult.error text in the thrown message for the proxy-specific reason (unknown connection, write failure, timeout) and address that root cause.
Example fix
// before — connection id captured once, reused after the 2s delay
const connId = connections[sourceNode.id][0];
await this.proxyController.sendToClient(connId, sMigratingNotification);
await setTimeout(2_000);
const migratedResult = await this.proxyController.sendToClient(connId, sMigratedNotification);
// after — re-resolve the live connection id right before the SMIGRATED send
const fresh = await this.proxyController.getConnections();
const liveConnId = fresh[sourceNode.id]?.[0];
if (!liveConnId) throw new Error('[Proxy] source connection gone before SMIGRATED');
const migratedResult = await this.proxyController.sendToClient(liveConnId, sMigratedNotification); Defensive patterns
Strategy: retry
Validate before calling
// Re-resolve the live connection id immediately before sending, and verify reachability
const fresh = await proxyController.getConnections();
const liveConnId = fresh[sourceNode.id]?.[0];
if (!liveConnId) {
throw new Error(`No live connection for node ${sourceNode.id}; cannot send SMIGRATED`);
}
// optionally: await proxyController.getStats() to confirm the proxy is responsive Try / catch
try {
const migratedResult = await proxyController.sendToClient(liveConnId, sMigratedNotification);
if (!migratedResult.success) throw new Error(migratedResult.error);
} catch (e) {
// Distinguish transient proxy/transport failure from a genuinely closed connection.
// Retry once after re-resolving connections; surface the proxy's reason to the test.
throw new Error(`SMIGRATED delivery failed for ${liveConnId}: ${(e as Error).message}`);
} Prevention
- Keep the cluster client connected for the whole migrate window; do not reconnect between SMIGRATING and SMIGRATED.
- Re-resolve connection ids from getConnections() right before each send rather than reusing a stale id.
- Confirm the proxy server is up (getStats) before starting a migrate action.
- Surface migratedResult.error in test diagnostics so the proxy-specific reason is visible.
When it happens
Trigger: Calling triggerAction({ type: 'migrate', parameters: { slot_migration, destination_type } }) on a ProxiedFaultInjectorClientForCluster when connections[sourceNode.id][0] — the connection used to deliver SMIGRATED — is closed, dropped, or no longer registered with the proxy between the SMIGRATING and SMIGRATED phases, or when the proxy controller's HTTP /send-to-client request itself fails.
Common situations: The cluster client disconnected or reconnected during the 2s simulated maintenance window; the proxy server was restarted or is unreachable; the connectionId resolved at migrate start went stale by the time SMIGRATED is sent; network interruption between the test process and the proxy controller HTTP endpoint.
Related errors
- [Proxy] Failed to send SMIGRATING notification: ${migratingR
- [Proxy] No node with no connections
- [Proxy] No destination node
- No slots to migrate
- All the root nodes are unavailable
AI-assisted analysis of redis/node-redis@90fd0652bc (2026-08-11).
Data as JSON: /api/errors/c9bc76f8a4434b77.
Report an issue: GitHub.