<table role="table">
<thead>
<tr>
<th>Q</th>
<th>A</th>
</tr>
</thead>
<tbody>
<tr>
<td>Bug report?</td>
<td>yes</td>
</tr>
<tr>
<td>Feature request?</td>
<td>no</td>
</tr>
<tr>
<td>BC Break report?</td>
<td>no</td>
</tr>
<tr>
<td>RFC?</td>
<td>no</td>
</tr>
<tr>
<td>Symfony version</td>
<td>3.2.6</td>
</tr>
</tbody>
</table>
<p dir="auto">According to the <a href="http://symfony.com/doc/master/reference/forms/types/text.html#empty-data" rel="nofollow">documentation</a> the default value of the <code class="notranslate">empty_data</code> option to <code class="notranslate">\Symfony\Component\Form\Extension\Core\Type\TextType</code> is the empty string <code class="notranslate">''</code>:</p>
<blockquote>
<p dir="auto">empty_data¶</p>
<p dir="auto">type: mixed</p>
<p dir="auto">The default value is '' (the empty string).</p>
</blockquote>
<p dir="auto">But I found when using 3.2.6, that the default of <code class="notranslate">empty_data</code> is actually <code class="notranslate">null</code>.<br>
I’m not sure if or where in the code this is actually defined, so I could not check against it.</p>
<table role="table">
<thead>
<tr>
<th>Q</th>
<th>A</th>
</tr>
</thead>
<tbody>
<tr>
<td>Bug report?</td>
<td>yes</td>
</tr>
<tr>
<td>Feature request?</td>
<td>no</td>
</tr>
<tr>
<td>BC Break report?</td>
<td>no</td>
</tr>
<tr>
<td>RFC?</td>
<td>no</td>
</tr>
<tr>
<td>Symfony version</td>
<td>master (likely 3.x and 2.x as well)</td>
</tr>
</tbody>
</table>
<p dir="auto">Consider a basic data class:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="class MyClass
{
  private $value = '';

  public function setValue(string $value)
  {
    $this-&gt;value = $value;
  }

  public function getValue(): string
  {
    return $this-&gt;value;
  }
}"><pre class="notranslate"><code class="notranslate">class MyClass
{
  private $value = '';

  public function setValue(string $value)
  {
    $this-&gt;value = $value;
  }

  public function getValue(): string
  {
    return $this-&gt;value;
  }
}
</code></pre></div>
<p dir="auto">Map a basic form with the field optional:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$form = $this-&gt;createFormBuilder(new MyClass())
            -&gt;add('value', TextareaType::class, [
                'required' =&gt; false,
            ])
            -&gt;add('create', SubmitType::class)
            -&gt;getForm();
// etc."><pre class="notranslate"><code class="notranslate">$form = $this-&gt;createFormBuilder(new MyClass())
            -&gt;add('value', TextareaType::class, [
                'required' =&gt; false,
            ])
            -&gt;add('create', SubmitType::class)
            -&gt;getForm();
// etc.
</code></pre></div>
<p dir="auto">Submit the form with the field empty and we get an <code class="notranslate">InvalidArgumentException</code>:</p>
<blockquote>
<p dir="auto">Expected argument of type "string", "NULL" given<br>
in vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php at line 275</p>
</blockquote>
<p dir="auto">As the value itself is empty, the Form sets its <code class="notranslate">$modelData</code> to <code class="notranslate">NULL</code>, while <code class="notranslate">$normData</code> and <code class="notranslate">$viewData</code> are correctly the empty string. <code class="notranslate">PropertyPathMapper::mapFormsToData</code> subsequently attempts to set the property to null, which would have been fine if not for the type hinting in the setter, causing the exception.</p>
<p dir="auto"><em>edit</em>: if I remove the type hint from the setter I then get a Doctrine error as the field itself is mandatory yet <code class="notranslate">NULL</code> was inserted. I most definitely want users to be able to have the empty string in there, not null. So this is in the Form component, not the PropertyAccess end doing as it's told.</p>