Why ConfigFormBase does not goes through custom construct() when using managed_file? First I want to state that this is a question. My Form is working, but I had, strangely, to add clauses for the case when my CustomForm extending ConfigFormBase did not goes as expected throught the __construct()
I created a config property in the __construct(). Then, I could access it from any function, and it worked fine.
As soon as I added a managed_file, things went wrong. Specifically, $this-&gt;config was null in validateForm and submitForm. I could restore the property easily by calling the factory again (and that's what I end up doing), but I'm confused.
What I see is the managed_file module send the form in XHR when updating the managed_file input. So when I'm validating the form, maybe there is a cache version or something that gets loaded, or the callback_func works differently. Anyway, the __construct() is executed on the XHR request (I checked with xdebug) but not after when I'm (re) submitting the form with the button.
I compared the stack when $this-&gt;config is null and when it's not, and did not spot any difference.
Maybe it's part of a multi-part Form functionality ?
I'm sure I'm getting it wrong somewhere.
Relevant parts as follow :
  /**
   * Constructs a \Drupal\system\ConfigFormBase object.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The factory for configuration objects.
   */
  public function __construct(ConfigFactoryInterface $config_factory) {
    $this-&gt;setConfigFactory($config_factory);
    $this-&gt;config = $this-&gt;config('custom.settings');

    parent::__construct($config_factory);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container-&gt;get('config.factory'),
    );


     }

/**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {

    $form['section5'][self::TAB_IMAGE] = [
      '#type' =&gt; 'managed_file',
      '#title' =&gt; $this-&gt;t(&quot;Image de l'onglet&quot;),
      '#default_value' =&gt; ($this-&gt;config-&gt;get(self::TAB_IMAGE)) ? [$this-&gt;config-&gt;get(self::TAB_IMAGE)] : NULL,
      '#upload_location' =&gt; 'public://',
      '#upload_validators' =&gt; [
        'file_validate_extensions' =&gt; ['gif png jpg jpeg'],
        'file_validate_size' =&gt; [Bytes::toInt(Environment::getUploadMaxSize())],
        'file_validate_image_resolution' =&gt; ['300x300'],
      ],
    ];
}


  /**
   * {@inheritdoc}
   */
  public function submitForm(array &amp;$form, FormStateInterface $form_state) {
    // When submitting a Form with managed_file, weirdly no __construct().
    if (!$this-&gt;config) {
      $this-&gt;config = $this-&gt;config('custom.settings');
    }
The difference could be that managed_file is using Ajax which is caching the form object.
If you want to have this property cached you would need to declare it as protected property:
class CustomForm extends ConfigFormBase {

  protected $config;

Normally $this-&gt;config() is the method FormBase::config as the main entry point to the config API, not a property you populate when constructing the form object. Using the same name could be quite confusing and it's also recommended to use the mentioned method to retrieve the config and declare the config in ConfigFormBase::getEditableConfigNames() if you intend to save it.