Saga token gets updated during exception

The following is my gradle kotlin spring-boot project’s configuration and saga:
person service application.properties:

spring.datasource.url=jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/demodb
spring.datasource.username=${DB_USER:postgres}
spring.datasource.password=${DB_PASSWORD:postgres}
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update
server.port=${PORT:8081}

store service application.properties:

spring.datasource.url=jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/demodb
spring.datasource.username=${DB_USER:postgres}
spring.datasource.password=${DB_PASSWORD:postgres}
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update
server.port=${PORT:8082}

using dependencies:

    org.axonframework:axon-bom version 4.6.0
    org.springframework.boot version 2.7.5
    kotlin version 1.6.21
    postgres

Using a saga:

package com.example.person

import com.example.common.PersonEvents
import com.example.common.StoreCommands as storeCommands
import com.example.common.StoreEvents as storeEvents

import com.example.common.PersonCommands as personCommands
import org.axonframework.commandhandling.gateway.CommandGateway
import org.axonframework.modelling.saga.EndSaga
import org.axonframework.modelling.saga.SagaEventHandler
import org.axonframework.modelling.saga.StartSaga
import org.axonframework.spring.stereotype.Saga
import org.springframework.beans.factory.annotation.Autowired

@Saga
class PersonShoppingSaga {
    @Transient
    @Autowired
    lateinit var commandGateway: CommandGateway

    lateinit var name: String
    var listNumber: Int = 0
    lateinit var shoppingList: List<String>
    var shopping: Boolean = false

    @StartSaga
    @SagaEventHandler(associationProperty = "name")
    fun handle(event: PersonEvents.shoppingListRecieved){
        if (shopping) {
            TODO() // person is already shopping, ask processor to wait longer.
        }

        shopping = true
        shoppingList = event.list
        name = event.name

        walkToStore()
    }

    @SagaEventHandler(associationProperty = "person", keyName = "name")
    fun handle(event: storeEvents.travelledToStore){
        listNumber ++
        walkToStore()
    }

    fun walkToStore(){
        if (listNumber == shoppingList.size -1) {
            commandGateway.sendAndWait<personCommands>(personCommands.finishedShopping(name, shoppingList))
        }
        commandGateway.sendAndWait<storeCommands>(storeCommands.travelToStore(shoppingList.get(listNumber), name))
    }

    @EndSaga
    @SagaEventHandler(associationProperty = "name")
    fun handle(event: PersonEvents.shoppingListCompleted){
        println("completed shopping list")
    }
}

When there is a random amount of chances for failure in the “travelToStore” command, when I run the example project, and restart the service, the saga does not retry consuming the event that caused an exception and continues consuming new events.

Is there some configuration that I can set to make the saga not continue with the next event untill the events were processed successfully?

I’m not sure where that error is triggered. It’s likely through you need to configure an error handler such that the error is not just logged.

So to be clear, the default behaviour for a saga is to only log the exception then continue?

I do think indeed the default error handler for all event processors, so also for the one handling saga’s is the LoggingErrorHandler.