Janitor jobs and other actions trigger twice

Hello there,

Since recently, different actions on our Online Shop based on Merx get triggered twice. Yesterday an order was created two times, and today a refund that gets triggered by a Janitor job was made twice.
We are currently using Kirby version 3.7.4 and PHP version 8.0.20.
I cannot really give more information since I don’t really know where to start searching for the problem. So maybe someone experienced something similar or can point me in a direction to start looking for the issue.
The shop is in German and English, so I thought maybe that could be the problem, but I am not sure.

Thank you in advance,

Can you reproduce the issue yourself? And then the code of the job would be interesting. But if you made no changes to your installation, maybe the hoster changed something?

Hi @texnixe, no I cannot reproduce it, but I am trying on my local environment, maybe I should set up another testing environment.
I updated Kirby and all plugins yesterday, and otherwise going to keep on searching.

Oh, and the code to the refund janitor job is the following:

'refund' => function (Kirby\Cms\Page $page = null, string $data = null) {

      if ($page->refundAmount() != '') {
        if ($page->paymentMethod() == 'credit-card-sca') {
          $stripe = new \Stripe\StripeClient(
            'payment_intent' => $page->stripepaymentintentid(),
            'amount' => $page->refundAmount()->toFloat() * 100,
        else {
          $id = $page->Paymentdetails()->toStructure()->toStructure();
          paypalrefund($page->refundAmount()->toFloat(), $id); //custom function


        return [
          'status' => 200,
          'label' => 'Erfolgreich.',
      } else {
        return [
          'status' => 200,
          'label' => 'Bitte Betrag manuell eingeben!',

I also tried to trigger another Janitor job myself that just sends a simple email and that did not fire twice so I think the Janitor plugin is not the issue.

I think it would be important to try and reproduce the issue either locally or in an environment that is the same as on production.

And first it would make sense to make sure that a user didn’t trigger the action twice because it somehow seemed to take too long, and they hit the button again, so it has nothing to do with any code/configuration but is a user error.

I have no experience with Merx nor do I know your custom code. But as I wrote above: If the same actions worked fine and no changes were made on your own side, try and find out if something changed on the server.

Yes, I agree. User error seems quite plausible. So maybe the first step would be to prevent double clicking the button.

if you want to be extra sure the process is not triggered twice you could instead of just using an if clause add a check for a custom lock file.

$lockfilepath = kirby()->roots('cache') . '/refund/' . md5($page->id()) . '.lock';
$hasLock = F::exists($lockfilepath);
if (!$hasLock && $page->refundAmount() != '') {
   F::write($lockfilepath, time());
   // do your stuff and then unlock
   F::unlink($lockfilepath); // like F::remove but with race condition handling

edited: needed md5 for filename or you will get lots of folders.

@bnomei Thank you, I am going to implement that.