Validation not running on empty custom fields on an entry (when creating programmatically) I'm trying to save an entry via a controller. They are contact form submission. A few of the fields are required.
    $section = Craft::$app-&gt;sections-&gt;getSectionByHandle('contactSubmissions');

    $entry = new Entry();
    $entry-&gt;sectionId = $section-&gt;id;
    $entry-&gt;typeId = 2;
    $entry-&gt;authorId = 1;
    $entry-&gt;enabled = true;

    $entry-&gt;setFieldValues([
        'contactName' =&gt; ucwords($data['contactName']),
        'contactEmail' =&gt; $data['contactEmail'],
        'contactCompany' =&gt; $data['contactCompany'],
        'contactMessage' =&gt; $data['contactMessage'],
        'contactHeardAbout' =&gt; $data['contactHeardAbout'],
        'contactWebsite' =&gt; $data['contactWebsite'],
        'contactTitle' =&gt; $data['contactTitle'],
    ]);

    
    if ( Craft::$app-&gt;elements-&gt;saveElement($entry) ) {
        //$this-&gt;sendMail($entry);
    }
    
    die(var_dump($entry-&gt;getErrors()));

    return $entry;

The only validation that runs if the missing title, which in this case is the contactName. All other keys in the $data array are empty strings. They do not trigger any validation and the empty entry saves into the database.
If I were to go into the control panel and try to save the entry, it would fail with the validation errors.
If I were to enter a value for the email field, but have an invalid email, that validation then gets triggered. But none of the empty fields do.

Additional info
Craft version: 3.6.10
PHP version: 7.3.13
You would need to set the entry's scenario to live just before saving the element.
$section = Craft::$app-&gt;sections-&gt;getSectionByHandle('contactSubmissions');

$entry = new Entry();
$entry-&gt;sectionId = $section-&gt;id;
$entry-&gt;typeId = 2;
$entry-&gt;authorId = 1;
$entry-&gt;enabled = true;

$entry-&gt;setFieldValues([
    'contactName' =&gt; ucwords($data['contactName']),
    'contactEmail' =&gt; $data['contactEmail'],
    'contactCompany' =&gt; $data['contactCompany'],
    'contactMessage' =&gt; $data['contactMessage'],
    'contactHeardAbout' =&gt; $data['contactHeardAbout'],
    'contactWebsite' =&gt; $data['contactWebsite'],
    'contactTitle' =&gt; $data['contactTitle'],
]);

$entry-&gt;setScenario(Entry::SCENARIO_LIVE);

if ( Craft::$app-&gt;elements-&gt;saveElement($entry) ) {
    //$this-&gt;sendMail($entry);
}

die(var_dump($entry-&gt;getErrors()));

return $entry;

Alternatively, If you want to save entries from the front-end, unless you have very specific requirements, you could use:

Guest entries plugin (if users are not logged in)
Make a front-end entry form (if users are logged in)