diff --git a/modules/nextflow/src/main/groovy/nextflow/script/WorkflowMetadata.groovy b/modules/nextflow/src/main/groovy/nextflow/script/WorkflowMetadata.groovy index e8c066cea0..af00db5be0 100644 --- a/modules/nextflow/src/main/groovy/nextflow/script/WorkflowMetadata.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/script/WorkflowMetadata.groovy @@ -29,6 +29,7 @@ import nextflow.NextflowMeta import nextflow.Session import nextflow.config.ConfigBuilder import nextflow.config.Manifest +import nextflow.exception.WorkflowScriptErrorException import nextflow.trace.WorkflowStats import nextflow.util.Duration import org.codehaus.groovy.runtime.InvokerHelper @@ -392,6 +393,10 @@ class WorkflowMetadata { try { action.call() } + catch (WorkflowScriptErrorException e) { + // re-throw it to allow `error` function to be invoked by completion handler + throw e + } catch (Exception e) { log.error("Failed to invoke `workflow.onComplete` event handler", e) } diff --git a/modules/nextflow/src/test/groovy/nextflow/script/WorkflowMetadataTest.groovy b/modules/nextflow/src/test/groovy/nextflow/script/WorkflowMetadataTest.groovy index 5cda717fff..05e370c612 100644 --- a/modules/nextflow/src/test/groovy/nextflow/script/WorkflowMetadataTest.groovy +++ b/modules/nextflow/src/test/groovy/nextflow/script/WorkflowMetadataTest.groovy @@ -22,6 +22,7 @@ import java.time.OffsetDateTime import nextflow.Const import nextflow.Session +import nextflow.exception.WorkflowScriptErrorException import nextflow.trace.TraceRecord import nextflow.trace.WorkflowStats import nextflow.trace.WorkflowStatsObserver @@ -171,6 +172,24 @@ class WorkflowMetadataTest extends Specification { } + def 'should be able to throw an error from onComplete handler' () { + + given: + def session = Spy(Session) + session.getStatsObserver() >> Mock(WorkflowStatsObserver) { getStats() >> new WorkflowStats() } + + def metadata = new WorkflowMetadata(session, null) + + when: + metadata.onComplete { + throw new WorkflowScriptErrorException('You failed!') + } + metadata.invokeOnComplete() + + then: + thrown(WorkflowScriptErrorException) + } + def 'should access workflow script variables onError' () { given: