Unable to set field collection field value on form validation
Use Computed field instead of doing it yourself! Don't use _validate, just use _compute.


Change field_total_cost to a computed field, saving as decimal.
Create a custom module and add the following (much clearer than using Computed Fields settings inputs - yuk)


Do something like the following :

/**
 * Computed field for - field_total_cost
 */
function computed_field_field_total_cost_compute(&amp;$entity_field, $entity_type, $entity, $field, $instance, $langcode, $items) {
  $tot   = 0;
  $books = 0;
  $rate  = 0;
  if (isset($entity-&gt;field_assigned_booklets[LANGUAGE_NONE][0]['value'])) {
    $books = $entity-&gt;field_assigned_booklets[LANGUAGE_NONE][0]['value'];
  }
  if (isset($entity-&gt;field_rate[LANGUAGE_NONE][0]['value'])) {
    $rate = $entity-&gt;field_rate[LANGUAGE_NONE][0]['value'];
  }
  $tot = $books * $rate;
  $entity_field[0]['value'] = number_format((float) $tot, 2, '.', '');
}

/**
 * Display for - field_total_cost
 */
function computed_field_field_total_cost_display($field, $entity_field_item, $entity_lang, $langcode, $entity) {
  return '£' . number_format($entity_field_item['value'], 2);
}


I obviously don't know what your calculations are like but you get the idea.
This will calculate and populate the Total Cost field per field collection.

OR

If you still want to do it on validate you (afaict) can't do it on node_validate but you can on a field validate. So you need to add a custom validate function to your Field Collection field, then it should work as you think.

Add a custom validate callback on hook_field_widget_form_alter

/**
 * Implements hook_field_widget_form_alter().
 */
function MYMODULE_field_widget_form_alter(&amp;$element, &amp;$form_state, $context) {
  // Add custom validation hooks for Field Collections.
  if ($context['field']['field_name'] == 'field_assignments') {
    array_unshift($element['#element_validate'], 'MYMODULE_field_assignments_validate');
  }
}


Create the custom validate function and set the value similar to how you suggested

/**
 * Custom validate function for field_assignments.
 *
 *  @see MYMODULE_field_widget_form_alter()
 */
function MYMODULE_field_assignments_validate($element, &amp;$form_state, $form) {    
  form_set_value($form["field_assignments"][LANGUAGE_NONE][0]['field_total_cost'], array(LANGUAGE_NONE =&gt; array(0 =&gt; array('value' =&gt; 123.456))), $form_state);
}


I obliviously left out any logic in this example, but you get the idea :)