int64           availMemLessRefund;
        int                     memtupsize = state->memtupsize;
 
+       /* Caller error if we have no tapes */
+       Assert(state->activeTapes > 0);
+
        /* For simplicity, assume no memtuples are actually currently counted */
        Assert(state->memtupcount == 0);
 
        refund = memtupsize * STANDARDCHUNKHEADERSIZE;
        availMemLessRefund = state->availMem - refund;
 
+       /*
+        * We need to be sure that we do not cause LACKMEM to become true, else
+        * the batch allocation size could be calculated as negative, causing
+        * havoc.  Hence, if availMemLessRefund is negative at this point, we must
+        * do nothing.  Moreover, if it's positive but rather small, there's
+        * little point in proceeding because we could only increase memtuples by
+        * a small amount, not worth the cost of the repalloc's.  We somewhat
+        * arbitrarily set the threshold at ALLOCSET_DEFAULT_INITSIZE per tape.
+        * (Note that this does not represent any assumption about tuple sizes.)
+        */
+       if (availMemLessRefund <=
+               (int64) state->activeTapes * ALLOCSET_DEFAULT_INITSIZE)
+               return;
+
        /*
         * To establish balanced memory use after refunding palloc overhead,
         * temporarily have our accounting indicate that we've allocated all
        state->growmemtuples = true;
        USEMEM(state, availMemLessRefund);
        (void) grow_memtuples(state);
-       /* Should not matter, but be tidy */
-       FREEMEM(state, availMemLessRefund);
        state->growmemtuples = false;
+       /* availMem must stay accurate for spacePerTape calculation */
+       FREEMEM(state, availMemLessRefund);
+       if (LACKMEM(state))
+               elog(ERROR, "unexpected out-of-memory situation in tuplesort");
 
 #ifdef TRACE_SORT
        if (trace_sort)