diff --git src/wp-admin/includes/image-edit.php src/wp-admin/includes/image-edit.php
index 99e1c40..5ae4c6f 100644
--- src/wp-admin/includes/image-edit.php
+++ src/wp-admin/includes/image-edit.php
@@ -827,6 +827,22 @@ function wp_save_image( $post_id ) {
 		$success = $delete = $nocrop = true;
 	}
 
+	/*
+	 * We need to remove any existing resized image files because
+	 * a new crop could generate different image file sizes and so
+	 * different file names, and so the new resized images won't
+	 * necessarily overwrite the existing resized image files
+	 * https://core.trac.wordpress.org/ticket/32171
+	*/
+	if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
+		foreach ( $meta['sizes'] as $size ) {
+			if ( preg_match('/-e[0-9]{13}-/', $size['file'] ) ) {
+				$delete_file = path_join( dirname( $new_path ), $size['file'] );
+				wp_delete_file( $delete_file );
+			}
+		}
+	}
+
 	if ( isset( $sizes ) ) {
 		$_sizes = array();
 
diff --git tests/phpunit/tests/ajax/MediaEdit.php tests/phpunit/tests/ajax/MediaEdit.php
index 7ef9469..2ec0756 100644
--- tests/phpunit/tests/ajax/MediaEdit.php
+++ tests/phpunit/tests/ajax/MediaEdit.php
@@ -51,4 +51,50 @@ class Tests_Ajax_MediaEdit extends WP_Ajax_UnitTestCase {
 		$this->assertArrayHasKey('sizes', $media_meta, 'cropped attachment should have size data');
 		$this->assertArrayHasKey('medium', $media_meta['sizes'], 'cropped attachment should have data for medium size');
 	}
+
+	/**
+	 * @ticket 32171
+	 */
+	public function testImageEditOverwriteConstant() {
+		define( 'IMAGE_EDIT_OVERWRITE', true );
+
+		include_once( ABSPATH . 'wp-admin/includes/image-edit.php' );
+
+		$filename = DIR_TESTDATA . '/images/canola.jpg';
+		$contents = file_get_contents( $filename );
+
+		$upload = wp_upload_bits( basename( $filename ), null, $contents );
+		$id = $this->_make_attachment( $upload );
+
+		$_REQUEST['action'] = 'image-editor';
+		$_REQUEST['context'] = 'edit-attachment';
+		$_REQUEST['postid'] = $id;
+		$_REQUEST['target'] = 'all';
+		$_REQUEST['do'] = 'save';
+		$_REQUEST['history'] = '[{"c":{"x":5,"y":8,"w":289,"h":322}}]';
+
+		$ret = wp_save_image( $id );
+
+		$media_meta = wp_get_attachment_metadata( $id );
+		$sizes1 = $media_meta['sizes'];
+
+		$_REQUEST['history'] = '[{"c":{"x":5,"y":8,"w":189,"h":322}}]';
+
+		$ret = wp_save_image( $id );
+
+		$media_meta = wp_get_attachment_metadata( $id );
+		$sizes2 = $media_meta['sizes'];
+
+		$file_path = dirname( get_attached_file( $id ) );
+
+		foreach ( $sizes1 as $key => $size ) {
+			if ( $sizes2[ $key ]['file'] !== $size['file'] ) {
+				$files_that_shouldnt_exist[] = $file_path . '/' . $size['file'];
+			}
+		}
+
+		foreach ( $files_that_shouldnt_exist as $file ) {
+			$this->assertFalse( file_exists( $file ), 'IMAGE_EDIT_OVERWRITE is leaving garbage image files behind.' );
+		}
+	}
 }
