redis/node-redis · error · Error

Action id: ${actionId} failed! Error: ${action.error}

Error message

Action id: ${actionId} failed! Error: ${action.error}

What it means

waitForAction polls getActionStatus for an action_id. If the fault-injector service reports status === 'failed', it throws immediately, embedding the server-side action.error. This fires before the maxWait timeout check, so a failed action short-circuits the wait.

Source

Thrown at packages/test-utils/lib/fault-injector/fault-injector-client.ts:117

    actionId: string,
    {
      timeoutMs,
      maxWaitTimeMs,
    }: {
      timeoutMs?: number;
      maxWaitTimeMs?: number;
    } = {}
  ): Promise<ActionStatus> {
    const timeout = timeoutMs || 1000;
    const maxWaitTime = maxWaitTimeMs || 60000;

    const startTime = Date.now();

    while (Date.now() - startTime < maxWaitTime) {
      const action = await this.getActionStatus<ActionStatus>(actionId);

      if (action.status === "failed") {
        throw new Error(
          `Action id: ${actionId} failed! Error: ${action.error}`
        );
      }

      if (["finished", "success"].includes(action.status)) {
        dbg(`${actionId} completed: ${action.status}`)
        return action;
      }

      await setTimeout(timeout);
    }

    throw new Error(`Timeout waiting for action ${actionId}`);
  }

  async migrateAndBindAction({
    bdbId,
    clusterIndex,

View on GitHub (pinned to 90fd0652bc)

Solutions

  1. Read action.error in the message — it is the server's reason for the failure
  2. Call getActionStatus(actionId) again or listActions to inspect the full action record
  3. Validate the parameters (cluster_index, bdb_id, database_config) against the cluster's current state before retriggering

Example fix

// before
await fi.triggerAction({ type: 'migrate', parameters: { cluster_index: 9 } });
// Error: Action id: abc failed! Error: cluster index 9 out of range

// after — use a valid cluster index
const clusters = await fi.listActions();
await fi.triggerAction({ type: 'migrate', parameters: { cluster_index: 0 } });
Defensive patterns

Strategy: try-catch

Type guard

function isFailedAction(a: ActionStatus): boolean {
  return a.status === 'failed';
}

Try / catch

try {
  await fi.triggerAction(action);
} catch (e) {
  if (e instanceof Error && /Action id:.*failed!/.test(e.message)) {
    const reason = e.message;
  }
  throw e;
}

Prevention

When it happens

Trigger: triggerAction(...) or migrateAndBindAction(...) where the fault-injector backend executes the action and it fails server-side (e.g., migrate target unreachable, database creation rejected, cluster index invalid).

Common situations: Requesting a migration to a cluster index that does not exist; bdb_id mismatch; create_database with invalid config; backend resource exhaustion; permissions on the target cluster.

Related errors


AI-assisted analysis of redis/node-redis@90fd0652bc (2026-08-11). Data as JSON: /api/errors/4d5177096d8dab9b. Report an issue: GitHub.