diff --git includes/ajax.inc includes/ajax.inc
index 1d4ea77..09262c4 100644
--- includes/ajax.inc
+++ includes/ajax.inc
@@ -286,7 +286,7 @@ function ajax_form_callback() {
 
   // This call recreates the form relying solely on the $form_state that
   // drupal_process_form() set up.
-  $form = drupal_rebuild_form($form_id, $form_state, $form_build_id);
+  $form = ajax_rebuild_form($form_id, $form_state, $form_build_id, $form);
 
   // $triggering_element_path in a simple form might just be 'myselect', which
   // would mean we should use the element $form['myselect']. For nested form
@@ -536,6 +536,63 @@ function ajax_process_form($element, &$form_state) {
 }
 
 /**
+ * Retrieves a form and caches it under the same build id.
+ *
+ * If your AJAX callback simulates the pressing of a button, then your AJAX
+ * callback will need to do the same as what drupal_get_form would do when the
+ * button is pressed: get the form from the cache, run drupal_process_form over
+ * it and then if it needs rebuild, run ajax_rebuild_form over it. Then send
+ * back a part of the returned form.
+ * $form_state['clicked_button']['#array_parents'] will help you to find which
+ * part.
+ *
+ * @param $form_id
+ *   The unique string identifying the desired form. If a function
+ *   with that name exists, it is called to build the form array.
+ *   Modules that need to generate the same form (or very similar forms)
+ *   using different $form_ids can implement hook_forms(), which maps
+ *   different $form_id values to the proper form constructor function. Examples
+ *   may be found in node_forms(), search_forms(), and user_forms().
+ * @param $form_state
+ *   A keyed array containing the current state of the form.
+ * @param $form_build_id
+ *   Form cache id used to re-cache the form under the same id.
+ * @param $old_form
+ *   The previous build of this form.
+ * @return
+ *   The newly built form.
+ */
+ function ajax_rebuild_form($form_id, &$form_state, $form_build_id, $old_form) {
+  // _form_builder_handle_input_element() needs to distinguish a
+  // rebuild from an initial build in order to process user input correctly.
+  // Form constructors and form processing functions may also need to handle a
+  // rebuild differently than an initial build.
+  $form_state['rebuild'] = TRUE;
+
+  $form = drupal_retrieve_form($form_id, $form_state);
+
+  $form['#build_id'] = $form_build_id;
+  drupal_prepare_form($form_id, $form, $form_state);
+
+  $form['#action'] = $old_form['#action'];
+
+  if (empty($form_state['no_cache'])) {
+    // We cache the form structure and the form state so it can be retrieved
+    // later for validation.
+    form_set_cache($form_build_id, $form, $form_state);
+  }
+
+  // Clear out all group associations as these might be different when
+  // re-rendering the form.
+  $form_state['groups'] = array();
+
+  // Do not call drupal_process_form(), as that would validate and submit the
+  // form
+  $form = form_builder($form_id, $form, $form_state);
+  return $form;
+}
+
+/**
  * @} End of "defgroup ajax".
  */
 
diff --git includes/form.inc includes/form.inc
index 4013f14..87d7edb 100644
--- includes/form.inc
+++ includes/form.inc
@@ -286,14 +286,6 @@ function form_state_defaults() {
 /**
  * Retrieves a form, caches it and processes it again.
  *
- * If your AHAH callback simulates the pressing of a button, then your AHAH
- * callback will need to do the same as what drupal_get_form would do when the
- * button is pressed: get the form from the cache, run drupal_process_form over
- * it and then if it needs rebuild, run drupal_rebuild_form over it. Then send
- * back a part of the returned form.
- * $form_state['clicked_button']['#array_parents'] will help you to find which
- * part.
- *
  * @param $form_id
  *   The unique string identifying the desired form. If a function
  *   with that name exists, it is called to build the form array.
@@ -303,34 +295,25 @@ function form_state_defaults() {
  *   may be found in node_forms(), search_forms(), and user_forms().
  * @param $form_state
  *   A keyed array containing the current state of the form.
- * @param $form_build_id
- *   If the AHAH callback calling this function only alters part of the form,
- *   then pass in the existing form_build_id so we can re-cache with the same
- *   csid.
  * @return
  *   The newly built form.
  */
-function drupal_rebuild_form($form_id, &$form_state, $form_build_id = NULL) {
-  // AJAX and other contexts may call drupal_rebuild_form() even when
-  // $form_state['rebuild'] isn't set, but _form_builder_handle_input_element()
-  // needs to distinguish a rebuild from an initial build in order to process
-  // user input correctly. Form constructors and form processing functions may
-  // also need to handle a rebuild differently than an initial build.
+function drupal_rebuild_form($form_id, &$form_state) {
+  // _form_builder_handle_input_element() needs to distinguish a
+  // rebuild from an initial build in order to process user input correctly.
+  // Form constructors and form processing functions may also need to handle a
+  // rebuild differently than an initial build.
   $form_state['rebuild'] = TRUE;
 
   $form = drupal_retrieve_form($form_id, $form_state);
 
-  if (!isset($form_build_id)) {
-    // We need a new build_id for the new version of the form.
-    $form_build_id = 'form-' . md5(mt_rand());
-  }
-  $form['#build_id'] = $form_build_id;
+  $form['#build_id'] = 'form-' . md5(mt_rand());
   drupal_prepare_form($form_id, $form, $form_state);
 
   if (empty($form_state['no_cache'])) {
     // We cache the form structure and the form state so it can be retrieved
     // later for validation.
-    form_set_cache($form_build_id, $form, $form_state);
+    form_set_cache($form['#build_id'], $form, $form_state);
   }
 
   // Clear out all group associations as these might be different when
diff --git modules/file/file.module modules/file/file.module
index f61c159..3df80a7 100644
--- modules/file/file.module
+++ modules/file/file.module
@@ -239,7 +239,7 @@ function file_ajax_upload() {
 
   // This call recreates the form relying solely on the form_state that the
   // drupal_process_form() set up.
-  $form = drupal_rebuild_form($form_id, $form_state, $form_build_id);
+  $form = ajax_rebuild_form($form_id, $form_state, $form_build_id, $form);
 
   // Retrieve the element to be rendered.
   foreach ($form_parents as $parent) {
