Hotwire Discussion

"Error: rendering is already in progress" when trying to perform Turbo navigation from submit-end event handler

Hello, I am trying to reset a modal form in the background when a 500 error occurs. The contents of this form lazy loads the /new object route. I seem to be able to successfully trigger the lazy load refresh by resetting the src attribute on the <turbo-frame>. (see How to auto-reload frame? - #5 by ledermann) However, when I do this from within the submit-end Stimulus event handler, it raises an error in my browser:

Here is my controller code. Weirdly, Turbo is undefined here even though it is available in other Stimulus controllers’ event handlers.

import { Controller } from "stimulus";
import { Turbo } from "@hotwired/turbo-rails";
import AlertsController from "./alerts_controller";

export default class extends Controller {
  static targets = ['closeButton', 'contentForm', 'dialog', 'refreshForm', 'validationErrorAlert'];

  connect() {
    // No validation error occurred so go ahead and close the modal since there's nothing more to display
    if(!this.hasValidationErrorAlertTarget) this.closeButtonTarget.click();
  }

  handleServerSideError() {
    let alerts_controller = new AlertsController;
    alerts_controller.createAlert('danger', 'A server side error has occurred');

    // Reload the lazy load of the modal form since the 500 error prevented a normal resetting of the form
    this.resetFrame();
  }

  resetFrame() {
    // Reset the value to the same thing. Turbo will detect the attribute access and reload.
    let frame = this.dialogTarget.closest('turbo-frame');
    frame?.setAttribute('src', frame.getAttribute('src'));
  }

  submitEnd(event) {
    console.log(`Turbo.status ${Turbo.navigator?.formSubmission?.state}`);
    console.log(`Turbo.session.started ${Turbo.session?.started}`);
    if (event.target != this.contentFormTarget) return;

    this.closeButtonTarget.click();
    if (!event.detail.success) this.handleServerSideError()

    console.log('form submission finished');
  }

}

Maybe I need to find some asynchronous way of triggering the frame?.setAttribute('src', frame.getAttribute('src'));?