Validate a custom type node before submitting I'm to validate the creation of a new content node, of a custom content type. It seems I cannot find the right hook.

I tried using hook_node_presave, however, the only way to stop node from creating is to throw an exception. This is rather user unfriendly.

 function custom_module_node_presave($node) {

    if($node-&gt;getType()=='custom_content_type'){
            if(some_business_rules_apply()){
                    drupal_set_message('You cannot add a new node.','error');
                    # cancel saving 
                    throw new \Exception(t('You cannot add a new node.'));
            }else{
                    # do something more
            }
    }
}


I tried to use hook_node_validate but it seems like it is not called. Do I miss something? Maybe, I use the wrong name for the hook function? Is there some kind of example for hook_node_validate?

function custom_type_node_validate(\Drupal\Core\Entity\EntityInterface $node, $form, &amp;$form_state){
    \Drupal::logger('My logger')-&gt;info('Node validate');
}
In Drupal 8 the hook hook_node_validate() has been removed. Here are some suggestions.

Reference: hook_node_validate() and hook_node_submit() have been removed.

Field constraints

If you're trying to validate an individual field,  use a constraint.

/**
 * Implements hook_entity_bundle_field_info_alter().
 */
function custom_general_entity_bundle_field_info_alter(&amp;$fields, EntityTypeInterface $entity_type, $bundle) {
  // Alter node.page.field_service.
  if ($entity_type-&gt;id() === 'node' &amp;&amp; $bundle === 'page') {
      $fields['field_service']-&gt;addConstraint('CustomAssignableService', []);
  }


Entity constraints

For general constraints on the entire entity or constraints which are not specific to a single field.

/**
 * Implements hook_entity_type_alter().
 */
function custom_general_entity_type_alter(array &amp;$entity_types) {
  if (isset($entity_types['node'])) {
    $entity_types['node']-&gt;addConstraint('CustomAuthorizedTerritory');
  }
}


Form validation

The "constraints" will always validate the field / entity no matter the form / method with which you use save the entity.

Additionally, you can provide form validation using a hook_node_form_alter() to improve the UX with nice error messages.

Note: These are "form-level" validations and are only applied when the node is created / updated from a said form. Users might be able to bypass these restrictions while saving the node using web services or other forms (if any).

// In the mymodule.module file.

/**
 * Implements hook_form_FORM_ID_form_alter().
 */
function mymodule_form_node_form_alter(&amp;$form, FormStateInterface $form_state) {
  $form['#validate'][] = 'mymodule_node_form_validate';
}

function mymodule_node_form_validate($form, FormStateInterface $form_state) {
  $node = $form_state-&gt;getFormObject()-&gt;getEntity();
  if ($node-&gt;getType() == 'custom_content_type') {
    if ($form_state-&gt;getValue('some_property') !== '123') {
      $form_state-&gt;setErrorByName('some_property', t('Property must be 123.'));
    }
  }
}