diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 161c2e2d3df..82ce25133ff 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -765,7 +765,7 @@ AllocSetAllocLarge(MemoryContext context, Size size, int flags)
 
 	chunk = (MemoryChunk *) (((char *) block) + ALLOC_BLOCKHDRSZ);
 
-	/* mark the MemoryChunk as externally managed */
+	/* mark the MemoryChunk as externally managed and valid */
 	MemoryChunkSetHdrMaskExternal(chunk, MCTX_ASET_ID);
 
 #ifdef MEMORY_CONTEXT_CHECKING
@@ -826,7 +826,7 @@ AllocSetAllocChunkFromBlock(MemoryContext context, AllocBlock block,
 	block->freeptr += (chunk_size + ALLOC_CHUNKHDRSZ);
 	Assert(block->freeptr <= block->endptr);
 
-	/* store the free list index in the value field */
+	/* store the free list index in the value field, and mark chunk valid */
 	MemoryChunkSetHdrMask(chunk, block, fidx, MCTX_ASET_ID);
 
 #ifdef MEMORY_CONTEXT_CHECKING
@@ -910,8 +910,8 @@ AllocSetAllocFromNewBlock(MemoryContext context, Size size, int flags,
 		block->freeptr += (availchunk + ALLOC_CHUNKHDRSZ);
 		availspace -= (availchunk + ALLOC_CHUNKHDRSZ);
 
-		/* store the freelist index in the value field */
-		MemoryChunkSetHdrMask(chunk, block, a_fidx, MCTX_ASET_ID);
+		/* store the freelist index in the value field, but mark chunk free */
+		MemoryChunkSetHdrMask(chunk, block, a_fidx, MCTX_UNUSED_CHUNK_ID);
 #ifdef MEMORY_CONTEXT_CHECKING
 		chunk->requested_size = InvalidAllocSize;	/* mark it free */
 #endif
@@ -1058,6 +1058,9 @@ AllocSetAlloc(MemoryContext context, Size size, int flags)
 		set->freelist[fidx] = link->next;
 		VALGRIND_MAKE_MEM_NOACCESS(link, sizeof(AllocFreeListLink));
 
+		/* mark chunk valid */
+		MemoryChunkSetMethodID(chunk, MCTX_ASET_ID);
+
 #ifdef MEMORY_CONTEXT_CHECKING
 		chunk->requested_size = size;
 		/* set mark to catch clobber of "unused" space */
@@ -1185,6 +1188,10 @@ AllocSetFree(void *pointer)
 #ifdef CLOBBER_FREED_MEMORY
 		wipe_mem(pointer, GetChunkSizeFromFreeListIdx(fidx));
 #endif
+
+		/* mark chunk free */
+		MemoryChunkSetMethodID(chunk, MCTX_UNUSED_CHUNK_ID);
+
 		/* push this chunk onto the top of the free list */
 		VALGRIND_MAKE_MEM_DEFINED(link, sizeof(AllocFreeListLink));
 		link->next = set->freelist[fidx];
diff --git a/src/include/utils/memutils_internal.h b/src/include/utils/memutils_internal.h
index 475e91b336b..9fa877332ee 100644
--- a/src/include/utils/memutils_internal.h
+++ b/src/include/utils/memutils_internal.h
@@ -138,6 +138,9 @@ typedef enum MemoryContextMethodID
 	MCTX_15_RESERVED_WIPEDMEM_ID	/* 1111 occurs in wipe_mem'd memory */
 } MemoryContextMethodID;
 
+/* This MemoryContextMethodID is recommended to put in pfree'd chunks */
+#define MCTX_UNUSED_CHUNK_ID	MCTX_0_RESERVED_UNUSEDMEM_ID
+
 /*
  * The number of bits that 8-byte memory chunk headers can use to encode the
  * MemoryContextMethodID.
diff --git a/src/include/utils/memutils_memorychunk.h b/src/include/utils/memutils_memorychunk.h
index bda9912182d..b876940d5e0 100644
--- a/src/include/utils/memutils_memorychunk.h
+++ b/src/include/utils/memutils_memorychunk.h
@@ -58,6 +58,9 @@
  * MemoryChunkSetHdrMaskExternal:
  *		Used to set up an externally managed MemoryChunk.
  *
+ * MemoryChunkSetMethodID:
+ *		Used to change a MemoryChunk's MethodID while preserving other fields.
+ *
  * MemoryChunkIsExternal:
  *		Determine if the given MemoryChunk is externally managed, i.e.
  *		MemoryChunkSetHdrMaskExternal() was called on the chunk.
@@ -196,6 +199,21 @@ MemoryChunkSetHdrMaskExternal(MemoryChunk *chunk,
 		methodid;
 }
 
+/*
+ * MemoryChunkSetMethodID:
+ *		Set the methodid without changing any other chunk header fields.
+ *		This is typically used while marking a chunk as free or not-free.
+ */
+static inline void
+MemoryChunkSetMethodID(MemoryChunk *chunk,
+					   MemoryContextMethodID methodid)
+{
+	Assert((int) methodid <= MEMORY_CONTEXT_METHODID_MASK);
+
+	chunk->hdrmask = (chunk->hdrmask & ~MEMORY_CONTEXT_METHODID_MASK) |
+		methodid;
+}
+
 /*
  * MemoryChunkIsExternal
  *		Return true if 'chunk' is marked as external.
