diff --git a/src/api-cursor.c b/src/api-cursor.c
index 4489a64f..4a506b41 100644
--- a/src/api-cursor.c
+++ b/src/api-cursor.c
@@ -712,22 +712,10 @@ int mdbx_cursor_put(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data, MDBX_p
   if (unlikely(rc != MDBX_SUCCESS))
     return LOG_IFERR(rc);
 
-  /* Check this first so counter will always be zero on any early failures. */
   if (unlikely(flags & MDBX_MULTIPLE)) {
-    if (unlikely(flags & MDBX_RESERVE))
-      return LOG_IFERR(MDBX_EINVAL);
-    if (unlikely(!(mc->tree->flags & MDBX_DUPFIXED)))
-      return LOG_IFERR(MDBX_INCOMPATIBLE);
-    const size_t dcount = data[1].iov_len;
-    if (unlikely(dcount < 2 || data->iov_len == 0))
-      return LOG_IFERR(MDBX_BAD_VALSIZE);
-    if (unlikely(mc->tree->dupfix_size != data->iov_len) && mc->tree->dupfix_size)
-      return LOG_IFERR(MDBX_BAD_VALSIZE);
-    if (unlikely(dcount > MAX_MAPSIZE / 2 / (BRANCH_NODE_MAX(MDBX_MAX_PAGESIZE) - NODESIZE))) {
-      /* checking for multiplication overflow */
-      if (unlikely(dcount > MAX_MAPSIZE / 2 / data->iov_len))
-        return LOG_IFERR(MDBX_TOO_LARGE);
-    }
+    rc = cursor_check_multiple(mc, key, data, flags);
+    if (unlikely(rc != MDBX_SUCCESS))
+      return LOG_IFERR(rc);
   }
 
   if (flags & MDBX_RESERVE) {
diff --git a/src/api-txn-data.c b/src/api-txn-data.c
index 2be54df8..cc0891cb 100644
--- a/src/api-txn-data.c
+++ b/src/api-txn-data.c
@@ -266,6 +266,19 @@ int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, MDBX_val *data, M
   rc = cursor_init(&cx.outer, txn, dbi);
   if (unlikely(rc != MDBX_SUCCESS))
     return LOG_IFERR(rc);
+
+  if (unlikely(flags & MDBX_MULTIPLE)) {
+    rc = cursor_check_multiple(&cx.outer, key, data, flags);
+    if (unlikely(rc != MDBX_SUCCESS))
+      return LOG_IFERR(rc);
+  }
+
+  if (flags & MDBX_RESERVE) {
+    if (unlikely(cx.outer.tree->flags & (MDBX_DUPSORT | MDBX_REVERSEDUP | MDBX_INTEGERDUP | MDBX_DUPFIXED)))
+      return LOG_IFERR(MDBX_INCOMPATIBLE);
+    data->iov_base = nullptr;
+  }
+
   cx.outer.next = txn->cursors[dbi];
   txn->cursors[dbi] = &cx.outer;
 
diff --git a/src/cursor.c b/src/cursor.c
index 9da14343..233c2246 100644
--- a/src/cursor.c
+++ b/src/cursor.c
@@ -1439,6 +1439,21 @@ insert_node:;
   return rc;
 }
 
+int cursor_check_multiple(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data, unsigned flags) {
+  (void)key;
+  if (unlikely(flags & MDBX_RESERVE))
+    return MDBX_EINVAL;
+  if (unlikely(!(mc->tree->flags & MDBX_DUPFIXED)))
+    return MDBX_INCOMPATIBLE;
+  const size_t number = data[1].iov_len;
+  if (unlikely(number > MAX_MAPSIZE / 2 / (BRANCH_NODE_MAX(MDBX_MAX_PAGESIZE) - NODESIZE))) {
+    /* checking for multiplication overflow */
+    if (unlikely(number > MAX_MAPSIZE / 2 / data->iov_len))
+      return MDBX_TOO_LARGE;
+  }
+  return MDBX_SUCCESS;
+}
+
 __hot int cursor_put_checklen(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data, unsigned flags) {
   cASSERT(mc, (mc->flags & z_inner) == 0);
   if (unlikely(key->iov_len > mc->clc->k.lmax || key->iov_len < mc->clc->k.lmin)) {
diff --git a/src/cursor.h b/src/cursor.h
index d8100999..d07be856 100644
--- a/src/cursor.h
+++ b/src/cursor.h
@@ -315,6 +315,9 @@ MDBX_INTERNAL MDBX_cursor *cursor_cpstk(const MDBX_cursor *csrc, MDBX_cursor *cd
 MDBX_INTERNAL int __must_check_result cursor_ops(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
                                                  const MDBX_cursor_op op);
 
+MDBX_INTERNAL int __must_check_result cursor_check_multiple(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data,
+                                                            unsigned flags);
+
 MDBX_INTERNAL int __must_check_result cursor_put_checklen(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data,
                                                           unsigned flags);