Error on hooks "Storage for the page is immutable and cannot be deleted"

I’m opening a new topic as this one is marked “solved”.

On the page.update:after event I need to update $newpage twice, but I get the following error:

Storage for the page is immutable and cannot be deleted. Make sure to use the last alteration of the object.

I know that $newPage is immutable, so I reassign the returned object, but I get the error anyway. Here is the snippet of code in my config.php file.

else if ($newPage->template() == "album")
      { 
        //Split artista e titolo
        $newPage = trackAlbumUpdate($newPage, $oldPage, false);

        //Lowercase tags
        $newPage = lowerCaseTags($newPage);
      }

Of course I could merge both functions into one, and update the page one time only, but It would mess up my code…

Any input?
Thanks
Francesco

And what do those functions do? Without their code, it’s hard to tell.

They both update the txt file.

//Splitta artista e titolo dell'album o della traccia e aggiorna i tag
//Trasfroma i tag in minuscolo e aggiorna la pagina
function trackAlbumUpdate($newPage, $oldPage, $isTitleChanged)
{
  $artist = "";
  $title = "";
  $tags = $newPage->tags()->yaml();
  
  //Dal titolo ricava artista e titolo del pezzo e lo scrive sul file
  try{
      $arr = explode(':',$newPage->title());
      if ($arr[0] > "") $artist = trim($arr[0]);
      if ($arr[1] > "") $title = trim($arr[1]);
  }
  catch(Exception $e) {}; //echo $e;}
  
  //Aggiorno i tag con il nome dell'artista, se cambiato, o se nessun tag è valorizzato

  $newTags = array();
  $newTags = $tags;
  
  if ($isTitleChanged || count($tags) == 0)
  {
    array_push($tags, $artist);                     //Aggiungo ai tag il nome dell'artista
    $newTags = array_unique($tags, SORT_STRING);    //Rendo unico il contenuto
  }

  return $newPage->update(array(
      'artist' => $artist, 
      'articleTitle' => $title,
      'tags' => strtolower(implode(',',$newTags))
  ));
}
//Trasfroma i tag in minuscolo
//Aggiorna la pagina
function lowerCaseTags($page)
{
  return $page->update(array(
    'tags' => strtolower($page->tags())
  ));
}

Why are you updating the page twice?

Some things look weird in your code. Given that $newPage->tags() is a standard tags field, you need to split it to get an array.

Secondly,

Why is the $newTags variable directly overwritten, this is unnecessary.

Try/catch is unnecessary here, non of this throws an error. The code can be shortened to:

$tags = $newPage->tags()->split();
$arr = explode(':',$newPage->title());
$artist = trim($arr[0] ?? '');
$title = trim($arr[1] ?? '');

Do you return the new page object in your hook?

Thanks @texnixe for pushing me to improve my code and @distantnative for trying to solve my problem. I completely refactored my code and now it works, due the fact I managed to update the page one time only.

The only thing I’d like to know if it’s normal to get the “Immutable storage” error when I update the page twice in the same hook.

It should not happen if we continue to use the newly returned object. Basically with v5, Kirby marks an object explicitly as immutable when returning a modified version of the object (e.g. when calling update). To avoid you keep using the old object with outdated content.

My guess is rather that the errors in your original code resulted in an outdated $newPage variable.