redis/node-redis · error · Error
HIMPORT PREPARE/DISCARD/DISCARDALL are not supported inside…
Error message
HIMPORT PREPARE/DISCARD/DISCARDALL are not supported inside MULTI/pipeline; call them on the client before the transaction
What it means
The client maintains a fieldset registry for HIMPORT transparency. MULTI/pipeline only stores raw args, so a HIMPORT PREPARE / DISCARD / DISCARDALL queued in a transaction would bypass the registry and silently diverge client state from server state. The client rejects these at the exec funnel. HIMPORT SET is allowed inside MULTI because it mutates no registry state.
Solutions
- Issue HIMPORT PREPARE on the client directly (outside MULTI) before building the transaction.
- Issue HIMPORT DISCARD/DISCARDALL on the client after the transaction completes.
- Keep only HIMPORT SET inside the multi block.
Example fix
// before const m = client.multi(); m.addCommand(['HIMPORT', 'PREPARE', fieldset]); m.hImportSet(fieldset, 'k', v); await m.exec(); // after await client.hImportPrepare(fieldset); const m = client.multi(); m.hImportSet(fieldset, 'k', v); await m.exec();
Defensive patterns
Strategy: validation
Validate before calling
const HIMPORT_SESSION = new Set(['PREPARE', 'DISCARD', 'DISCARDALL']);
function assertNoHimportInMulti(commands) {
for (const { args } of commands) {
if (String(args[0]).toUpperCase() === 'HIMPORT' && HIMPORT_SESSION.has(String(args[1]).toUpperCase())) {
throw new Error('HIMPORT PREPARE/DISCARD/DISCARDALL cannot be queued in MULTI; call them on the client directly');
}
}
} Prevention
- Run HIMPORT PREPARE/DISCARD directly on the client; never inside multi().
- Keep only HIMPORT SET inside transactions.
- Document the registry-affecting subcommands so other contributors do not queue them.
When it happens
Trigger: Queuing HIMPORT PREPARE/DISCARD/DISCARDALL via multi.addCommand(['HIMPORT','PREPARE',...]) and then exec(), or via typed multi methods, then calling exec().
Common situations: Trying to batch HIMPORT session setup inside a transaction for perceived atomicity; refactoring existing HIMPORT calls into a multi block without realising the registry implication.
Related errors
- commands failed, see .replies and .errorIndexes for more…
- All statistics values must be non-negative
- "arguments[ ]" must be of type "string | Buffer", got…
- Cannot split : key region does not align with keystep
- Cannot split : key region overruns the arguments
AI-assisted analysis of redis/node-redis@90fd0652bc (2026-08-11).
Data as JSON: /api/errors/a8b5272fcc3c35d9.
Report an issue: GitHub.
Appendix: source
Thrown at packages/client/lib/client/index.ts:52
import { ASKING_CMD } from '../commands/ASKING';
const noop = () => {};
const HIMPORT_SESSION_SUBCOMMANDS = new Set(['PREPARE', 'DISCARD', 'DISCARDALL']);
/**
* MULTI/pipeline stores raw args only, so the HIMPORT transparency hook never sees these
* commands — a PREPARE/DISCARD executed that way would silently diverge the client registry
* from server state (a fieldset the registry doesn't know about, or a discarded one it
* would resurrect via lazy prepare). Rejected client-side at the exec funnel, which covers
* both the typed multi methods and raw `multi.addCommand(...)`. HIMPORT SET stays allowed:
* it mutates no registry state (the fieldset must already exist on the carrying connection).
*/
function assertNoHimportSessionCommands(commands: Array<RedisMultiQueuedCommand>) {
for (const { args } of commands) {
if (String(args[0]).toUpperCase() !== 'HIMPORT') continue;
if (HIMPORT_SESSION_SUBCOMMANDS.has(String(args[1]).toUpperCase())) {
throw new Error(
'HIMPORT PREPARE/DISCARD/DISCARDALL are not supported inside MULTI/pipeline; call them on the client before the transaction'
);
}
}
}
export interface RedisClientOptions<
M extends RedisModules = RedisModules,
F extends RedisFunctions = RedisFunctions,
S extends RedisScripts = RedisScripts,
RESP extends RespVersions = 3,
TYPE_MAPPING extends TypeMapping = TypeMapping,
SocketOptions extends RedisSocketOptions = RedisSocketOptions
> extends CommanderConfig<M, F, S, RESP> {
/**
* `redis[s]://[[username][:password]@][host][:port][/db-number]`
* See [`redis`](https://www.iana.org/assignments/uri-schemes/prov/redis) and [`rediss`](https://www.iana.org/assignments/uri-schemes/prov/rediss) IANA registration for more details
*/View on GitHub (pinned to 90fd0652bc)