diff --git src/wp-includes/taxonomy.php src/wp-includes/taxonomy.php
index 1d93f69..a0d8ee3 100644
--- src/wp-includes/taxonomy.php
+++ src/wp-includes/taxonomy.php
@@ -3352,15 +3352,33 @@ function wp_update_term( $term_id, $taxonomy, $args = array() ) {
 	 */
 	$parent = apply_filters( 'wp_update_term_parent', $args['parent'], $term_id, $taxonomy, $parsed_args, $args );
 
-	// Check for duplicate slug
-	$id = $wpdb->get_var( $wpdb->prepare( "SELECT term_id FROM $wpdb->terms WHERE slug = %s", $slug ) );
-	if ( $id && ($id != $term_id) ) {
-		// If an empty slug was passed or the parent changed, reset the slug to something unique.
-		// Otherwise, bail.
-		if ( $empty_slug || ( $parent != $term['parent']) )
-			$slug = wp_unique_term_slug($slug, (object) $args);
-		else
-			return new WP_Error('duplicate_term_slug', sprintf(__('The slug &#8220;%s&#8221; is already in use by another term'), $slug));
+	$parsed_args['parent'] = $parent;
+
+	// Ensure a unique slug.
+	$unique_slug = wp_unique_term_slug( $slug, (object) $parsed_args );
+
+	/*
+	 * If the unique slug is different from the 'slug' param, bail with an error. Exception: A term with a changed
+	 * parent may have had its slug updated to match the new parent, which should not throw an error.
+	 */
+	if ( ! $empty_slug && $slug !== $unique_slug && ( ! is_taxonomy_hierarchical( $taxonomy ) || empty( $parent ) ) ) {
+		return new WP_Error( 'duplicate_term_slug', sprintf( __( 'The slug &#8220;%s&#8221; is already in use by another term' ), $slug ) );
+	}
+
+	$slug = $unique_slug;
+
+	// Terms with duplicate names are not allowed at the same level of a taxonomy hierarchy.
+	$exists = get_term_by( 'name', $name, $taxonomy );
+	if ( $exists && $exists->term_id !== $term_id && $name === $exists->name ) {
+		if ( is_taxonomy_hierarchical( $taxonomy ) ) {
+			$siblings = get_terms( $taxonomy, array( 'fields' => 'names', 'get' => 'all', 'parent' => $parent ) );
+			if ( in_array( $name, $siblings ) ) {
+				return new WP_Error( 'term_exists', __( 'A term with the name and slug already exists with this parent.' ), $exists->term_id );
+			}
+
+		} else {
+			return new WP_Error( 'term_exists', __( 'A term with the name and slug already exists in this taxonomy.' ), $exists->term_id );
+		}
 	}
 
 	$tt_id = $wpdb->get_var( $wpdb->prepare( "SELECT tt.term_taxonomy_id FROM $wpdb->term_taxonomy AS tt INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = %s AND t.term_id = %d", $taxonomy, $term_id) );
diff --git tests/phpunit/tests/term.php tests/phpunit/tests/term.php
index 2cf5fb2..fc59aa4 100644
--- tests/phpunit/tests/term.php
+++ tests/phpunit/tests/term.php
@@ -640,7 +640,7 @@ class Tests_Term extends WP_UnitTestCase {
 	/**
 	 * @ticket 5809
 	 */
-	public function test_wp_update_term_duplicate_slug_same_taxonomy() {
+	public function test_wp_update_term_should_not_create_duplicate_slugs_within_the_same_taxonomy() {
 		register_taxonomy( 'wptests_tax', 'post' );
 
 		$t1 = $this->factory->term->create( array(
@@ -650,7 +650,7 @@ class Tests_Term extends WP_UnitTestCase {
 		) );
 
 		$t2 = $this->factory->term->create( array(
-			'name' => 'Foo',
+			'name' => 'Bar',
 			'slug' => 'bar',
 			'taxonomy' => 'wptests_tax',
 		) );
@@ -666,7 +666,7 @@ class Tests_Term extends WP_UnitTestCase {
 	/**
 	 * @ticket 5809
 	 */
-	public function test_wp_update_term_duplicate_slug_different_taxonomy() {
+	public function test_wp_update_term_should_allow_duplicate_slugs_in_different_taxonomy() {
 		register_taxonomy( 'wptests_tax', 'post' );
 		register_taxonomy( 'wptests_tax_2', 'post' );
 
@@ -686,8 +686,114 @@ class Tests_Term extends WP_UnitTestCase {
 			'slug' => 'foo',
 		) );
 
+		$this->assertFalse( is_wp_error( $updated ) );
+
+		$t1_term = get_term( $t1, 'wptests_tax' );
+		$t2_term = get_term( $t2, 'wptests_tax_2' );
+		$this->assertSame( $t1_term->slug, $t2_term->slug );
+	}
+
+	/**
+	 * @ticket 30780
+	 */
+	public function test_wp_update_term_should_allow_duplicate_names_in_different_taxonomies() {
+		register_taxonomy( 'wptests_tax', 'post' );
+		register_taxonomy( 'wptests_tax_2', 'post' );
+
+		$t1 = $this->factory->term->create( array(
+			'name' => 'Foo',
+			'slug' => 'foo',
+			'taxonomy' => 'wptests_tax',
+		) );
+
+		$t2 = $this->factory->term->create( array(
+			'name' => 'Bar',
+			'slug' => 'bar',
+			'taxonomy' => 'wptests_tax_2',
+		) );
+
+		$updated = wp_update_term( $t2, 'wptests_tax_2', array(
+			'name' => 'Foo',
+		) );
+
+		$this->assertFalse( is_wp_error( $updated ) );
+
+		$t2_term = get_term( $t2, 'wptests_tax_2' );
+		$this->assertSame( 'Foo', $t2_term->name );
+	}
+
+	/**
+	 * @ticket 30780
+	 */
+	public function test_wp_update_term_should_allow_duplicate_names_at_different_levels_of_the_same_taxonomy() {
+		register_taxonomy( 'wptests_tax', 'post', array(
+			'hierarchical' => true,
+		) );
+
+		$t1 = $this->factory->term->create( array(
+			'name' => 'Foo',
+			'slug' => 'foo',
+			'taxonomy' => 'wptests_tax',
+		) );
+
+		$t2 = $this->factory->term->create( array(
+			'name' => 'Bar',
+			'slug' => 'bar',
+			'taxonomy' => 'wptests_tax',
+			'parent' => $t1,
+		) );
+
+		$t3 = $this->factory->term->create( array(
+			'name' => 'Bar Child',
+			'slug' => 'bar-child',
+			'taxonomy' => 'wptests_tax',
+			'parent' => $t2,
+		) );
+
+		$updated = wp_update_term( $t3, 'wptests_tax', array(
+			'name' => 'Bar',
+		) );
+
+		$this->assertFalse( is_wp_error( $updated ) );
+
+		$t3_term = get_term( $t3, 'wptests_tax' );
+		$this->assertSame( 'Bar', $t3_term->name );
+	}
+
+	/**
+	 * @ticket 30780
+	 */
+	public function test_wp_update_term_should_not_allow_duplicate_names_at_same_level_of_the_same_taxonomy() {
+		register_taxonomy( 'wptests_tax', 'post', array(
+			'hierarchical' => true,
+		) );
+
+		$t1 = $this->factory->term->create( array(
+			'name' => 'Foo',
+			'slug' => 'foo',
+			'taxonomy' => 'wptests_tax',
+		) );
+
+		$t2 = $this->factory->term->create( array(
+			'name' => 'Bar',
+			'slug' => 'bar',
+			'taxonomy' => 'wptests_tax',
+			'parent' => $t1,
+		) );
+
+		$t3 = $this->factory->term->create( array(
+			'name' => 'Bar 2',
+			'slug' => 'bar-2',
+			'taxonomy' => 'wptests_tax',
+			'parent' => $t1,
+		) );
+
+		$updated = wp_update_term( $t3, 'wptests_tax', array(
+			'name' => 'Bar',
+		) );
+
 		$this->assertWPError( $updated );
-		$this->assertSame( 'duplicate_term_slug', $updated->get_error_code() );
+		$this->assertSame( 'term_exists', $updated->get_error_code() );
 	}
 
 	public function test_wp_update_term_alias_of_no_term_group() {
