diff --git includes/form.inc includes/form.inc
index a13a43c..b492bc8 100644
--- includes/form.inc
+++ includes/form.inc
@@ -163,7 +163,7 @@
  *   Any additional arguments are passed on to the functions called by
  *   drupal_get_form(), including the unique form constructor function. For
  *   example, the node_edit form requires that a node object is passed in here
- *   when it is called. These are available to implementations of 
+ *   when it is called. These are available to implementations of
  *   hook_form_alter() and hook_form_FORM_ID_alter() as the array
  *   $form_state['build_info']['args'].
  *
@@ -1428,7 +1428,8 @@ function form_set_error($name = NULL, $message = '', $limit_validation_errors =
         // section, then the element's values are within the part of
         // $form_state['values'] that the clicked button requires to be valid,
         // so errors for this element must be recorded.
-        if (array_slice(explode('][', $name), 0, count($section)) === $section) {
+        $section_string = implode('][', $section);
+        if (strpos($name, $section_string) === 0) {
           $record = TRUE;
           break;
         }
diff --git modules/field/field.api.php modules/field/field.api.php
index a701923..f8f82b9 100644
--- modules/field/field.api.php
+++ modules/field/field.api.php
@@ -764,7 +764,7 @@ function hook_field_widget_info_alter(&$info) {
  * definitions returned by field_info_field() and field_info_instance().
  * Examples: mono-value widget even if the field is multi-valued, non-required
  * widget even if the field is 'required'...
-
+ *
  * Therefore, the FAPI element callbacks (such as #process, #element_validate,
  * #value_callback...) used by the widget cannot use the field_info_field()
  * or field_info_instance() functions to retrieve the $field or $instance
diff --git modules/field/field.attach.inc modules/field/field.attach.inc
index 5a496e7..eea140b 100644
--- modules/field/field.attach.inc
+++ modules/field/field.attach.inc
@@ -456,11 +456,11 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) {
  *   // to access the field sub-array when $langcode is unknown.
  *   'field_foo' => array(
  *     '#tree' => TRUE,
+ *     '#parents' => @todo,
  *     '#field_name' => the name of the field,
  *     '#language' => $langcode,
  *     $langcode => array(
  *       '#field_name' => the name of the field,
- *       '#tree' => TRUE,
  *       '#required' => whether or not the field is required,
  *       '#title' => the label of the field instance,
  *       '#description' => the description text for the field instance,
@@ -497,7 +497,7 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) {
  * )
  * @endcode
  *
- * Sample structure for $form_state['field']:
+ * @todo Sample structure for $form_state['field']:
  * @code
  * array(
  *   // One sub-array per field appearing in the form, keyed by field name.
@@ -536,7 +536,9 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) {
  *   parameter. Processing information is added by reference in
  *   $form_state['field'].
  */
-function field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode = NULL) {
+function field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode = NULL, $parents = array()) {
+  field_form_set_parents($parents, $form_state);
+
   // If no language is provided use the default site language.
   $options = array('language' => field_valid_language($langcode));
   $form += (array) _field_invoke_default('form', $entity_type, $entity, $form, $form_state, $options);
@@ -553,6 +555,8 @@ function field_attach_form($entity_type, $entity, &$form, &$form_state, $langcod
     $function = $module . '_field_attach_form';
     $function($entity_type, $entity, $form, $form_state, $langcode);
   }
+
+  field_form_unset_parents($form_state);
 }
 
 /**
@@ -786,7 +790,9 @@ function field_attach_validate($entity_type, $entity) {
  * @param $form_state
  *   An associative array containing the current state of the form.
  */
-function field_attach_form_validate($entity_type, $entity, $form, &$form_state) {
+function field_attach_form_validate($entity_type, $entity, $form, &$form_state, $parents = array()) {
+  field_form_set_parents($parents, $form_state);
+
   // Extract field values from submitted values.
   _field_invoke_default('extract_form_values', $entity_type, $entity, $form, $form_state);
 
@@ -798,12 +804,16 @@ function field_attach_form_validate($entity_type, $entity, $form, &$form_state)
     // Pass field-level validation errors back to widgets for accurate error
     // flagging.
     foreach ($e->errors as $field_name => $field_errors) {
-      foreach ($field_errors as $langcode => $language_errors) {
-        $form_state['field'][$field_name][$langcode]['errors'] = $language_errors;
+      foreach ($field_errors as $langcode => $errors) {
+        $field_state = field_form_get_state(NULL, $field_name, $langcode, $form_state);
+        $field_state['errors'] = $errors;
+        field_form_set_state(NULL, $field_name, $langcode, $form_state, $field_state);
       }
     }
     _field_invoke_default('form_errors', $entity_type, $entity, $form, $form_state);
   }
+
+  field_form_unset_parents($form_state);
 }
 
 /**
@@ -823,7 +833,9 @@ function field_attach_form_validate($entity_type, $entity, $form, &$form_state)
  * @param $form_state
  *   An associative array containing the current state of the form.
  */
-function field_attach_submit($entity_type, $entity, $form, &$form_state) {
+function field_attach_submit($entity_type, $entity, $form, &$form_state, $parents = array()) {
+  field_form_set_parents($parents, $form_state);
+
   // Extract field values from submitted values.
   _field_invoke_default('extract_form_values', $entity_type, $entity, $form, $form_state);
 
@@ -835,6 +847,8 @@ function field_attach_submit($entity_type, $entity, $form, &$form_state) {
     $function = $module . '_field_attach_submit';
     $function($entity_type, $entity, $form, $form_state);
   }
+
+  field_form_unset_parents($form_state);
 }
 
 /**
diff --git modules/field/field.default.inc modules/field/field.default.inc
index 1353bd6..da46a8d 100644
--- modules/field/field.default.inc
+++ modules/field/field.default.inc
@@ -12,12 +12,15 @@
  */
 
 function field_default_extract_form_values($entity_type, $entity, $field, $instance, $langcode, &$items, $form, &$form_state) {
-  $field_name = $field['field_name'];
+  $parents = field_form_get_parents($form_state);
 
-  if (isset($form_state['values'][$field_name][$langcode])) {
-    $items = $form_state['values'][$field_name][$langcode];
+  $path = array_merge($parents, array($field['field_name'], $langcode));
+  $path_exists = FALSE;
+  $values = drupal_array_get_nested_value($form_state['values'], $path, $path_exists);
+  if ($path_exists) {
     // Remove the 'value' of the 'add more' button.
-    unset($items['add_more']);
+    unset($values['add_more']);
+    $items = $values;
   }
 }
 
diff --git modules/field/field.form.inc modules/field/field.form.inc
index c3ac156..eac7715 100644
--- modules/field/field.form.inc
+++ modules/field/field.form.inc
@@ -16,6 +16,8 @@ function field_default_form($entity_type, $entity, $field, $instance, $langcode,
     list($id, , ) = entity_extract_ids($entity_type, $entity);
   }
 
+  $parents = field_form_get_parents($form_state);
+
   $addition = array();
   $field_name = $field['field_name'];
   $addition[$field_name] = array();
@@ -37,6 +39,20 @@ function field_default_form($entity_type, $entity, $field, $instance, $langcode,
   // Collect widget elements.
   $elements = array();
   if (field_access('edit', $field, $entity_type, $entity)) {
+    // Store field information in $form_state.
+    if (!field_form_get_state(NULL, $field_name, $langcode, $form_state)) {
+      $field_state = array(
+        'field' => $field,
+        'instance' => $instance,
+        'items_count' => count($items),
+        // This entry will be populated at form build time.
+        'array_parents' => array(),
+        // This entry will be populated at form validation time.
+        'errors' => array(),
+      );
+      field_form_set_state(NULL, $field_name, $langcode, $form_state, $field_state);
+    }
+
     // If field module handles multiple values for this form element, and we
     // are displaying an individual element, process the multiple value form.
     if (!isset($get_delta) && field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
@@ -54,6 +70,8 @@ function field_default_form($entity_type, $entity, $field, $instance, $langcode,
           '#bundle' => $instance['bundle'],
           '#field_name' => $field_name,
           '#language' => $langcode,
+          // Provide $parents so that widgets can navigate in $form_state['field'].
+          '#field_parents' => $parents,
           '#columns' => array_keys($field['columns']),
           '#title' => check_plain(t($instance['label'])),
           '#description' => field_filter_xss($instance['description']),
@@ -79,16 +97,6 @@ function field_default_form($entity_type, $entity, $field, $instance, $langcode,
   }
 
   if ($elements) {
-    // Store field information in $form_state.
-    $form_state['field'][$field_name][$langcode] = array(
-      'field' => $field,
-      'instance' => $instance,
-      // This entry will be populated at form build time.
-      'array_parents' => array(),
-      // This entry will be populated at form validation time.
-      'errors' => array(),
-    );
-
     // Also aid in theming of field widgets by rendering a classified
     // container.
     $addition[$field_name] = array(
@@ -110,8 +118,10 @@ function field_default_form($entity_type, $entity, $field, $instance, $langcode,
   $elements['#after_build'][] = 'field_form_element_after_build';
   $elements['#field_name'] = $field_name;
   $elements['#language'] = $langcode;
+  $elements['#field_parents'] = $parents;
 
   $addition[$field_name] += array(
+    '#parents' => array_merge($parents, array($field_name)),
     '#tree' => TRUE,
     // The '#language' key can be used to access the field's form element
     // when $langcode is unknown.
@@ -136,16 +146,10 @@ function field_multiple_value_form($field, $instance, $langcode, $items, &$form,
   // Determine the number of widgets to display.
   switch ($field['cardinality']) {
     case FIELD_CARDINALITY_UNLIMITED:
-      $filled_items = _field_filter_items($field, $items);
-      $current_item_count = isset($form_state['field_item_count'][$field_name])
-                            ? $form_state['field_item_count'][$field_name]
-                            : count($items);
-      // We always want at least one empty icon for the user to fill in.
-      $max = ($current_item_count > count($filled_items))
-              ? $current_item_count - 1
-              : $current_item_count;
-
+      $field_state = field_form_get_state(NULL, $field_name, $langcode, $form_state);
+      $max = $field_state['items_count'];
       break;
+
     default:
       $max = $field['cardinality'] - 1;
       break;
@@ -153,7 +157,11 @@ function field_multiple_value_form($field, $instance, $langcode, $items, &$form,
 
   $title = check_plain(t($instance['label']));
   $description = field_filter_xss(t($instance['description']));
-  $wrapper_id = drupal_html_id($field_name . '-add-more-wrapper');
+
+  $parents = field_form_get_parents($form_state);
+  $id_prefix = implode('-', array_merge($parents, array($field_name)));
+  $wrapper_id = drupal_html_id($id_prefix . '-add-more-wrapper');
+
   $field_elements = array();
 
   $function = $instance['widget']['module'] . '_field_widget_form';
@@ -165,6 +173,8 @@ function field_multiple_value_form($field, $instance, $langcode, $items, &$form,
         '#bundle' => $instance['bundle'],
         '#field_name' => $field_name,
         '#language' => $langcode,
+        // Provide $parents so that widgets can navigate in $form_state['field'].
+        '#field_parents' => $parents,
         '#columns' => array_keys($field['columns']),
         // For multiple fields, title and description are handled by the wrapping table.
         '#title' => $multiple ? '' : $title,
@@ -209,10 +219,10 @@ function field_multiple_value_form($field, $instance, $langcode, $items, &$form,
       if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED && empty($form_state['programmed'])) {
         $field_elements['add_more'] = array(
           '#type' => 'submit',
-          '#name' => $field_name . '_add_more',
+          '#name' => strtr($id_prefix, '-', '_') . '_add_more',
           '#value' => t('Add another item'),
           '#attributes' => array('class' => array('field-add-more-submit')),
-          '#limit_validation_errors' => array(array($field_name, $langcode)),
+          '#limit_validation_errors' => array(array_merge($parents, array($field_name, $langcode))),
           '#submit' => array('field_add_more_submit'),
           '#ajax' => array(
             'callback' => 'field_add_more_js',
@@ -223,6 +233,7 @@ function field_multiple_value_form($field, $instance, $langcode, $items, &$form,
           // find the relevant field using those entries.
           '#field_name' => $field_name,
           '#language' => $langcode,
+          '#field_parents' => $parents,
         );
       }
     }
@@ -319,7 +330,11 @@ function theme_field_multiple_value_form($variables) {
 function field_form_element_after_build($element, &$form_state) {
   $field_name = $element['#field_name'];
   $langcode = $element['#language'];
-  $form_state['field'][$field_name][$langcode]['array_parents'] = $element['#array_parents'];
+  $parents = $element['#field_parents'];
+
+  $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
+  $field_state['array_parents'] = $element['#array_parents'];
+  field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
 
   return $element;
 }
@@ -328,21 +343,17 @@ function field_form_element_after_build($element, &$form_state) {
  * Transfer field-level validation errors to widgets.
  */
 function field_default_form_errors($entity_type, $entity, $field, $instance, $langcode, $items, $form, &$form_state) {
-  $field_name = $field['field_name'];
-  $field_info = $form_state['field'][$field_name][$langcode];
+  $field_state = field_form_get_state(NULL, $field['field_name'], $langcode, $form_state);
 
-  if (!empty($field_info['errors'])) {
+  if (!empty($field_state['errors'])) {
     $function = $instance['widget']['module'] . '_field_widget_error';
     $function_exists = function_exists($function);
 
-    // Walk the form down to where the widget lives.
-    $element = $form;
-    foreach ($field_info['array_parents'] as $key) {
-      $element = $element[$key];
-    }
+    // Locate the widget in the form.
+    $element = drupal_array_get_nested_value($form_state['complete form'], $field_state['array_parents']);
 
     $multiple_widget = field_behaviors_widget('multiple values', $instance) != FIELD_BEHAVIOR_DEFAULT;
-    foreach ($field_info['errors'] as $delta => $delta_errors) {
+    foreach ($field_state['errors'] as $delta => $delta_errors) {
       // For multiple single-value widgets, pass errors by delta.
       // For a multiple-value widget, all errors are passed to the main widget.
       $error_element = $multiple_widget ? $element : $element[$delta];
@@ -353,10 +364,13 @@ function field_default_form_errors($entity_type, $entity, $field, $instance, $la
         else {
           // Make sure that errors are reported (even incorrectly flagged) if
           // the widget module fails to implement hook_field_widget_error().
-          form_error($error_element, $error['error'], $form, $form_state);
+          form_error($error_element, $error['error']);
         }
       }
     }
+    // Reinitialize the errors list for the next submit.
+    $field_state['errors'] = array();
+    field_form_set_state(NULL, $field['field_name'], $langcode, $form_state, $field_state);
   }
 }
 
@@ -372,9 +386,12 @@ function field_default_form_errors($entity_type, $entity, $field, $instance, $la
 function field_add_more_submit($form, &$form_state) {
   $field_name = $form_state['clicked_button']['#field_name'];
   $langcode = $form_state['clicked_button']['#language'];
-  if ($form_state['values'][$field_name . '_add_more']) {
-    $form_state['field_item_count'][$field_name] = count($form_state['values'][$field_name][$langcode]);
-  }
+  $parents = $form_state['clicked_button']['#field_parents'];
+
+  $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
+  $field_state['items_count']++;
+  field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
+
   $form_state['rebuild'] = TRUE;
 }
 
@@ -390,21 +407,19 @@ function field_add_more_js($form, $form_state) {
   // Retrieve field information.
   $field_name = $form_state['clicked_button']['#field_name'];
   $langcode = $form_state['clicked_button']['#language'];
-  $field_info = $form_state['field'][$field_name][$langcode];
-  $field = $field_info['field'];
+  $parents = $form_state['clicked_button']['#field_parents'];
+
+  $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
 
+  $field = $field_state['field'];
   if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED) {
     return;
   }
 
-  // Navigate to the right element in the the form.
-  $element = $form;
+  // Locate the widget element.
+  $element = drupal_array_get_nested_value($form, $field_state['array_parents']);
 
-  foreach ($field_info['array_parents'] as $key) {
-    $element = $element[$key];
-  }
-
-  // Add a DIV around the new field to receive the AJAX effect.
+  // Add a DIV around the delta receiving the AJAX effect.
   $delta = $element['#max_delta'];
   $element[$delta]['#prefix'] = '<div class="ajax-new-content">' . (isset($element[$delta]['#prefix']) ? $element[$delta]['#prefix'] : '');
   $element[$delta]['#suffix'] = (isset($element[$delta]['#suffix']) ? $element[$delta]['#suffix'] : '') . '</div>';
@@ -412,6 +427,62 @@ function field_add_more_js($form, $form_state) {
   return $element;
 }
 
+function field_form_set_parents($parents, &$form_state) {
+  if (!isset($form_state['field']['parents_stack'])) {
+    $form_state['field']['parents_stack'] = array();
+  }
+  array_push($form_state['field']['parents_stack'], $parents);
+}
+
+function field_form_unset_parents(&$form_state) {
+  if (!empty($form_state['field']['parents_stack'])) {
+    array_pop($form_state['field']['parents_stack']);
+  }
+  else {
+    $form_state['field']['parents_stack'] = array();
+  }
+}
+
+function field_form_get_parents(&$form_state) {
+  return (!empty($form_state['field']['parents_stack'])) ? end($form_state['field']['parents_stack']) : array();
+}
+
+function field_form_set_state($parents, $field_name, $language, &$form_state, $field_state) {
+  $path = _field_form_state_path($parents, $field_name, $language, $form_state);
+  drupal_array_set_nested_value($form_state['field'], $path, $field_state);
+}
+
+function field_form_get_state($parents, $field_name, $language, &$form_state) {
+  $path = _field_form_state_path($parents, $field_name, $language, $form_state);
+  return drupal_array_get_nested_value($form_state['field'], $path);
+}
+
+function _field_form_state_path($parents, $field_name, $language, $form_state) {
+  // If no explicit $parents, use the current parents.
+  if ($parents === NULL) {
+    $parents = field_form_get_parents($form_state);
+  }
+
+  // To ensure backwards compatibility on regular entity fotms for widgets that
+  // still access $form_state['field'][$field_name] directly,
+  // - top-level fields (empty $parents) are placed directly under
+  //   $form_state['fields'][$field_name].
+  // - Other fields are placed under
+  //   $form_state['field']['#parents'][... $parents ...]['#fields'][$field_name]
+  //   to avoid clashes between field names and $parents parts.
+  // @todo Remove backwards compatibility in Drupal 8, and use a unique
+  // $form_state['field'][... $parents ...]['#fields'][$field_name] structure.
+  if (!empty($parents)) {
+    $path = array_merge(array('#parents'), $parents, array('#fields'));
+  }
+  else {
+    $path = array();
+  }
+  $path = array_merge($path, array($field_name, $language));
+
+  return $path;
+}
+
 /**
  * Retrieves the field definition for a widget's helper callbacks.
  *
@@ -432,8 +503,8 @@ function field_add_more_js($form, $form_state) {
  *   The $field definition array for the current widget.
  */
 function field_widget_field($element, $form_state) {
-  $info = $form_state['field'][$element['#field_name']][$element['#language']];
-  return $info['field'];
+  $field_state = field_form_get_state($element['#field_parents'], $element['#field_name'], $element['#language'], $form_state);
+  return $field_state['field'];
 }
 
 /**
@@ -456,6 +527,6 @@ function field_widget_field($element, $form_state) {
  *   The $instance definition array for the current widget.
  */
 function field_widget_instance($element, $form_state) {
-  $info = $form_state['field'][$element['#field_name']][$element['#language']];
-  return $info['instance'];
+  $field_state = field_form_get_state($element['#field_parents'], $element['#field_name'], $element['#language'], $form_state);
+  return $field_state['instance'];
 }
diff --git modules/field_ui/field_ui.admin.inc modules/field_ui/field_ui.admin.inc
index 6ac8be9..608d5ef 100644
--- modules/field_ui/field_ui.admin.inc
+++ modules/field_ui/field_ui.admin.inc
@@ -1917,16 +1917,20 @@ function field_ui_default_value_widget($field, $instance, &$form, &$form_state)
     '#collapsible' => FALSE,
     '#tree' => TRUE,
     '#description' => t('The default value for this field, used when creating new content.'),
-    // Make sure the values appear at the top-level of $form_state['values'].
-    '#parents' => array(),
   );
 
   // Insert the widget.
   $items = $instance['default_value'];
   $instance['required'] = FALSE;
   $instance['description'] = '';
+
   // @todo Allow multiple values (requires more work on 'add more' JS handler).
+
+  // Stick to an empty 'parents' on this form in order not to breaks widgets
+  // that don't use field_widget_[field|instance]().
+  field_form_set_parents(array(), $form_state);
   $element += field_default_form(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $form, $form_state, 0);
+  field_form_unset_parents($form_state);
 
   return $element;
 }
@@ -1935,13 +1939,21 @@ function field_ui_default_value_widget($field, $instance, &$form, &$form_state)
  * Form validation handler for field instance settings form.
  */
 function field_ui_field_edit_form_validate($form, &$form_state) {
+  // Take the incoming values as the $instance definition, so that the 'default
+  // value' gets validated using the instance settings being submitted.
   $instance = $form_state['values']['instance'];
   $field_name = $instance['field_name'];
-  $field = field_info_field($field_name);
+  $element = $form['instance']['default_value_widget'];
+
+  field_form_set_parents($element['#parents'], $form_state);
+
+  $field_state = field_form_get_state(NULL, $field_name, LANGUAGE_NONE, $form_state);
+  $field = $field_state['field'];
 
   // Extract the 'default value'.
   $items = array();
-  field_default_extract_form_values(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $form, $form_state);
+  field_default_extract_form_values(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $element, $form_state);
+
   // Validate the value and report errors.
   $errors = array();
   $function = $field['module'] . '_field_validate';
@@ -1949,9 +1961,14 @@ function field_ui_field_edit_form_validate($form, &$form_state) {
     $function(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $errors);
   }
   if (isset($errors[$field_name][LANGUAGE_NONE])) {
-    $form_state['field'][$field_name][LANGUAGE_NONE]['errors'] = $errors[$field_name][LANGUAGE_NONE];
-    field_default_form_errors(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $form, $form_state);
+    // Store reported errors in $form_state.
+    $field_state['errors'] = $errors[$field_name][LANGUAGE_NONE];
+    field_form_set_state(NULL, $field_name, LANGUAGE_NONE, $form_state, $field_state);
+    // Assign reported errors to the correct form element.
+    field_default_form_errors(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $element, $form_state);
   }
+
+  field_form_unset_parents($form_state);
 }
 
 /**
@@ -1967,11 +1984,15 @@ function field_ui_field_edit_form_submit($form, &$form_state) {
   field_update_field($field);
 
   // Handle the default value.
+  $element = $form['instance']['default_value_widget'];
+  field_form_set_parents($element['#parents'], $form_state);
+
   // Extract field values.
   $items = array();
-  field_default_extract_form_values(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $form, $form_state);
-  // Prepare field values.
-  field_default_submit(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $form, $form_state);
+  field_default_extract_form_values(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $element, $form_state);
+  field_default_submit(NULL, NULL, $field, $instance, LANGUAGE_NONE, $items, $element, $form_state);
+  field_form_unset_parents($form_state);
+
   $instance['default_value'] = $items ? $items : NULL;
 
   // Retrieve the stored instance settings to merge with the incoming values.
