{"id":"cd9e30c81091ebe2","repo":"redis/node-redis","slug":"errorindexes-length-commands-failed-see-repli","errorCode":null,"errorMessage":"${errorIndexes.length} commands failed, see .replies and .errorIndexes for more information","messagePattern":"(.+?) commands failed, see \\.replies and \\.errorIndexes for more information","errorType":"exception","errorClass":"MultiErrorReply","httpStatus":null,"severity":"error","filePath":"packages/client/lib/multi-command.ts","lineNumber":74,"sourceCode":"\n    redisArgs.push(...args);\n\n    this.addCommand(redisArgs, transformReply);\n  }\n  \n  transformReplies(rawReplies: Array<unknown>): Array<unknown> {\n    const errorIndexes: Array<number> = [],\n      replies = rawReplies.map((reply, i) => {\n        if (reply instanceof ErrorReply) {\n          errorIndexes.push(i);\n          return reply;\n        }\n\n        const { transformReply, args } = this.queue[i];\n        return transformReply ? transformReply(reply, args.preserve, this.typeMapping) : reply;\n      });\n\n    if (errorIndexes.length) throw new MultiErrorReply(replies, errorIndexes);\n    return replies;\n  }\n}\n","sourceCodeStart":56,"sourceCodeEnd":78,"githubUrl":"https://github.com/redis/node-redis/blob/bb5beb56578573910e2ee8f39681edc214c41398/packages/client/lib/multi-command.ts#L56-L78","documentation":"A MultiErrorReply thrown by RedisMultiCommand.transformReplies after a MULTI/EXEC (or pipeline) batch where at least one individual reply is an ErrorReply. It bundles every reply and the indexes that failed so callers can inspect which commands errored without losing the successful ones. The thrown object exposes .replies, .errorIndexes, and an .errors() generator.","triggerScenarios":"Executing multi.exec(true) (typed/generic mode) where one queued command produced a server-side ErrorReply — e.g. a type error, WRONGTYPE, arity error, or a WATCH conditional abort (EXECABORT surfaces differently). Any pipeline/multi whose raw replies include Error instances.","commonSituations":"Batching heterogeneous commands where one key has the wrong type; a LUA script error in one slot of the pipeline; optimistic concurrency with WATCH where individual commands reject; one malformed command in a bulk batch.","solutions":["Catch the error and iterate err.errorIndexes / err.errors() to see which commands failed and why.","Fix the individual command that produced the ErrorReply (read err.replies[i].message for the underlying cause).","If partial success is acceptable, read err.replies for the non-error slots and proceed.","Separate risky commands into their own transaction to isolate failures."],"exampleFix":"// before\nconst replies = await multi.get('k1').set('k2','v2').exec();\n\n// after\ntry {\n  const replies = await multi.get('k1').set('k2','v2').exec();\n} catch (e) {\n  if (e.errorIndexes) {\n    for (const [i, err] of e.errors()) console.error(`cmd #${i}:`, err.message);\n    const ok = e.replies.filter((_, idx) => !e.errorIndexes.includes(idx));\n  } else throw e;\n}","handlingStrategy":"try-catch","validationCode":"// Cannot validate server-side command outcomes ahead of exec(). Validate inputs\n// (types, arity) per queued command to reduce failures.","typeGuard":"function isMultiErrorReply(e) { return e instanceof Error && Array.isArray(e.errorIndexes) && Array.isArray(e.replies); }","tryCatchPattern":"try { return await multi.exec(); } catch (e) { if (isMultiErrorReply(e)) { for (const [i, err] of e.errors()) log(`#${i}`, err.message); return e.replies; } throw e; }","preventionTips":["Validate each queued command's key types/arity before exec.","Inspect err.errorIndexes and err.errors() to localize failures.","Isolate risky commands in their own transaction to avoid poisoning the batch."],"tags":["multi","pipeline","transaction","batch","error-aggregation"],"analyzedSha":"bb5beb56578573910e2ee8f39681edc214c41398","analyzedAt":"2026-08-03T19:09:15.686Z","schemaVersion":2}