How to rebuild form after AJAX call
First problem is to handle the value for the column number. On the first build get it from configuration, on a rebuild get it from the user input and put it in $columnNum.

The second is to decide, what part of the form changes in AJAX and put this in a div container with the id columns-wrapper.

class AJAXexample extends BlockBase {
    public function blockForm($form, FormStateInterface $form_state) {
        $columnNum = empty($form_state-&gt;getValue('columnNum')) ? $this-&gt;configuration['columnNum'] : $form_state-&gt;getValue('columnNum');
        $form['columnNum'] = [
            '#title'   =&gt; t('Number of Columns'),
            '#type'    =&gt; 'select',
            '#options' =&gt; [
                1         =&gt; '1',
                2         =&gt; '2',
                3         =&gt; '3',
                4         =&gt; '4',
            ],
            '#default_value' =&gt; $this-&gt;configuration['columnNum'],
            '#empty_option'  =&gt; t('-select-'),
            '#ajax'          =&gt; [
                'callback'      =&gt; [$this, 'columnCallback'],
                'wrapper'       =&gt; 'columns-wrapper', 
            ],
        ];
        $form['column'] = [
            '#type' =&gt; 'container',
            '#attributes' =&gt; ['id' =&gt; 'columns-wrapper'],
        ];
        for ($i = 0; $i &lt; $columnNum; $i += 1) {
            $form['column'][$i] = [
                $i =&gt; [
                    '#type'       =&gt; 'details',
                    '#title'      =&gt; t('Column '.$numTitle),
                    '#open'       =&gt; FALSE,
                    'columnTitle' =&gt; [
                        '#type'      =&gt; 'textfield',
                        '#title'     =&gt; t('Column Title'),
                        '#value'     =&gt; $config[0]['columnTitle'],
                    ],  
                ],
            ];  
        return $form;
    }


In the callback we only need to return the ajax wrapper.

public function columnCallback(array&amp;$form, FormStateInterface $form_state) {
    return $form['column'];
}


Drupal rebuilds the form on every ajax request and puts it in the parameter $form of the callback. It would make no sense to try to rebuild it again.