nextflow-io / nextflow-io/nextflow

GoogleBatch errors about Project exists - How to handle retries

Open
#6,916 3 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

executor/google-batch
Dominant language
Groovy
Stars
3.5k
Forks
811
Avg merge
2d 11h
Merged PRs (30d)
61

Description

Bug report

Expected behavior and actual behavior

Hello everyone, every now and then we receive errors grom Google Batch API in our pipeline running on Google Cloud that we cannot handle by retries. These seem to be related to the Batch API and therefore nextflow fails to produce an exit code and the entire workflow fails.
For example:

ERROR ~ Error executing process > 'vcf_sort_zip_and_index_merged (1)'

Caused by:
  ALREADY_EXISTS: Resource "projects/907794457535/locations/europe-west1/jobs/nf-06071afa-1773255240303" already exists


 -- Check '/mnt/stateful_partition/work/logs/158294/20260311-1431/nextflow.log' file for details
Steps to reproduce the problem

The pipeline runs within a e2-medium machine that is launching batch jobs for tasks (processes that are intensive). The cmd used to launch nextflow can be found in the traceback below

subprocess.CalledProcessError: Command '['nextflow', '-log', '/mnt/stateful_partition/work/logs/158294/20260311-1431/nextflow.log', 'run', 'targeted_onco', '-pi', '60s', '-profile', 'googlecloud', '--task_id', '158294', '--git_branch', 'gcap_v8_helios', '--git_sha1_hash', '7bd6646246f0b8f8f7da585830e571cbb963d429', '--project_id', 'diagnostics-uz', '--topic_id', 'gcap_nf_service', '--pubsub_message_id', '18631455654071366']' returned non-zero exit status 1.
Program output
Mar-11 19:55:01.379 [Task submitter] ERROR nextflow.processor.TaskProcessor - Error executing process > 'vcf_sort_zip_and_index_merged (1)'

Caused by:
  ALREADY_EXISTS: Resource "projects/907794457535/locations/europe-west1/jobs/nf-06071afa-1773255240303" already exists


com.google.api.gax.rpc.AlreadyExistsException: io.grpc.StatusRuntimeException: ALREADY_EXISTS: Resource "projects/907794457535/locations/europe-west1/jobs/nf-06071afa-1773255240303" already exists
        at com.google.api.gax.rpc.ApiExceptionFactory.createException(ApiExceptionFactory.java:96)
        at com.google.api.gax.grpc.GrpcApiExceptionFactory.create(GrpcApiExceptionFactory.java:98)
        at com.google.api.gax.grpc.GrpcApiExceptionFactory.create(GrpcApiExceptionFactory.java:66)
        at com.google.api.gax.grpc.GrpcExceptionCallable$ExceptionTransformingFuture.onFailure(GrpcExceptionCallable.java:97)
        at com.google.api.core.ApiFutures$1.onFailure(ApiFutures.java:84)
        at com.google.common.util.concurrent.Futures$CallbackListener.run(Futures.java:1128)
        at com.google.common.util.concurrent.DirectExecutor.execute(DirectExecutor.java:31)
        at com.google.common.util.concurrent.AbstractFuture.executeListener(AbstractFuture.java:1298)
        at com.google.common.util.concurrent.AbstractFuture.complete(AbstractFuture.java:1059)
        at com.google.common.util.concurrent.AbstractFuture.setException(AbstractFuture.java:809)
        at io.grpc.stub.ClientCalls$GrpcFuture.setException(ClientCalls.java:568)
        at io.grpc.stub.ClientCalls$UnaryStreamToFuture.onClose(ClientCalls.java:538)
        at io.grpc.PartialForwardingClientCallListener.onClose(PartialForwardingClientCallListener.java:39)
        at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:23)
        at io.grpc.ForwardingClientCallListener$SimpleForwardingClientCallListener.onClose(ForwardingClientCallListener.java:40)
        at com.google.api.gax.grpc.ChannelPool$ReleasingClientCall$1.onClose(ChannelPool.java:570)
        at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:567)
        at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:71)
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:735)
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:716)
        at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
        at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1583)
        Suppressed: com.google.api.gax.rpc.AsyncTaskException: Asynchronous task failed
                at com.google.api.gax.rpc.ApiExceptions.callAndTranslateApiException(ApiExceptions.java:57)
                at com.google.api.gax.rpc.UnaryCallable.call(UnaryCallable.java:112)
                at com.google.cloud.batch.v1.BatchServiceClient.createJob(BatchServiceClient.java:316)
                at com.google.cloud.batch.v1.BatchServiceClient.createJob(BatchServiceClient.java:248)
                at nextflow.cloud.google.batch.client.BatchClient$_submitJob_lambda1.doCall(BatchClient.groovy:98)
                at dev.failsafe.Functions.lambda$toCtxSupplier$11(Functions.java:236)
                at dev.failsafe.Functions.lambda$get$0(Functions.java:46)
                at dev.failsafe.internal.RetryPolicyExecutor.lambda$apply$0(RetryPolicyExecutor.java:75)
                at dev.failsafe.SyncExecutionImpl.executeSync(SyncExecutionImpl.java:176)
                at dev.failsafe.FailsafeExecutor.call(FailsafeExecutor.java:437)
                at dev.failsafe.FailsafeExecutor.get(FailsafeExecutor.java:115)
                at nextflow.cloud.google.batch.client.BatchClient.apply(BatchClient.groovy:187)
                at nextflow.cloud.google.batch.client.BatchClient.submitJob(BatchClient.groovy:98)
                at nextflow.cloud.google.batch.GoogleBatchTaskHandler.submit(GoogleBatchTaskHandler.groovy:166)
                at nextflow.processor.TaskPollingMonitor.submit(TaskPollingMonitor.groovy:218)
                at nextflow.processor.TaskPollingMonitor.submitPendingTasks(TaskPollingMonitor.groovy:599)
                at nextflow.processor.TaskPollingMonitor.submitLoop(TaskPollingMonitor.groovy:413)
                at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
                at java.base/java.lang.reflect.Method.invoke(Method.java:580)
                at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:343)
                at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:328)
                at groovy.lang.MetaClassImpl.doInvokeMethod(MetaClassImpl.java:1333)
                at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1088)
                at groovy.lang.MetaClassImpl.invokeMethodClosure(MetaClassImpl.java:1017)
                at groovy.lang.MetaClassImpl.doInvokeMethod(MetaClassImpl.java:1207)
                at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1088)
                at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1007)
                at groovy.lang.Closure.call(Closure.java:433)
                at groovy.lang.Closure.call(Closure.java:412)
                at groovy.lang.Closure.run(Closure.java:505)
                at java.base/java.lang.VirtualThread.run(VirtualThread.java:309)
Caused by: io.grpc.StatusRuntimeException: ALREADY_EXISTS: Resource "projects/907794457535/locations/europe-west1/jobs/nf-06071afa-1773255240303" already exists
        at io.grpc.Status.asRuntimeException(Status.java:537)
        ... 14 common frames omitted
Mar-11 19:55:01.416 [Task submitter] DEBUG nextflow.Session - Session aborted -- Cause: io.grpc.StatusRuntimeException: ALREADY_EXISTS: Resource "projects/907794457535/locations/europe-west1/jobs/nf-06071afa-1773255240303" already exists
Environment
  • Nextflow version: 24.04.4
  • Operating system: Linux
  • Java: openjdk 21.0.1 2023-10-17
  • Bash version: GNU bash, version 5.2.21(1)-release (x86_64-pc-linux-gnu)
Additional context

The Turn-around time for our pipeline is short since it is developed for diagnostic purposes and we would like to minimize such errors by implementing exception or retry strategies to avoid restarting (which has to be done from the beginning -> we do not use the -resume option due to our internal execution logging). Below is the configuration from our config

googlecloud {
    bucketDir = "gs://gcap-nf-scratch"
    docker.enabled = true

    process {
      withLabel: lotsOfWork {
        executor = 'google-batch'
        errorStrategy = { sleep(Math.pow(2, task.attempt) * 200 as long); return 'retry' }
        maxRetries = 10
      }

      // Default configuration for processes without labels
      errorStrategy = { sleep(Math.pow(2, task.attempt) * 200 as long); return 'retry' }
      maxRetries = 10
    }

    google {
      batch.spot = false
      batch.requestTimeout = '120 sec'
      location = 'europe-west1'
      project = 'diagnostics-uz'
      httpReadTimeout = '1h'
      httpConnectTimeout = '1h'
      storage.maxDelay = '1h'
      client.deadline = '120 sec'
      retries = 5
      retryInterval = '20 sec'
      maxRetryInterval = '2 min'
      batch.debug = true
      batch.sshDaemon = true
      batch.bootDiskSize = '100.GB'
    }

 }
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Google Batch submission path shown in nextflow.cloud.google.batch.client.BatchClient.groovy, especially submitJob and apply, then trace how GoogleBatchTaskHandler.groovy handles the failed submission. Reproduce the ALREADY_EXISTS response with the reported retry configuration and verify that the resulting behavior no longer aborts the workflow unexpectedly.

Written by the indexing model from the issue text.

Assessment

Tech stack
google-cloud, groovy
Domain
cloud
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.