James Fellows Yates
04/30/2026, 7:11 AMMaxime Garcia
04/30/2026, 7:11 AMJames Fellows Yates
04/30/2026, 7:12 AMJames Fellows Yates
04/30/2026, 7:12 AMJames Fellows Yates
04/30/2026, 7:13 AMMaxime Garcia
04/30/2026, 7:13 AMJames Fellows Yates
04/30/2026, 7:13 AMJames Fellows Yates
04/30/2026, 7:13 AMJames Fellows Yates
04/30/2026, 7:13 AMJames Fellows Yates
04/30/2026, 7:14 AMMaxime Garcia
04/30/2026, 7:14 AMJames Fellows Yates
04/30/2026, 7:18 AMMaxime Garcia
04/30/2026, 7:19 AMjava.util.ConcurrentModificationException?
James Fellows Yates
04/30/2026, 7:19 AMJames Fellows Yates
04/30/2026, 7:20 AMMaxime Garcia
04/30/2026, 7:20 AMMaxime Garcia
04/30/2026, 7:21 AMMaxime Garcia
04/30/2026, 7:21 AMMaxime Garcia
04/30/2026, 7:25 AMJames Fellows Yates
04/30/2026, 8:22 AMMaxime Garcia
04/30/2026, 8:24 AMJim Downie
04/30/2026, 8:24 AMEssentially, the ConcurrentModificationException is used to fail-fast when something we are iterating on is modified.https://www.baeldung.com/java-concurrentmodificationexception Something is being modified somewhere when it shouldn't be - would take a look at anywhere you have iterations via
collect or meta-map modification, maybe?James Fellows Yates
04/30/2026, 8:25 AMJames Fellows Yates
04/30/2026, 8:25 AMJames Fellows Yates
04/30/2026, 8:25 AMJim Downie
04/30/2026, 8:25 AMJames Fellows Yates
04/30/2026, 8:26 AMFIND , but occasioanlly in downstream processesJim Downie
04/30/2026, 8:32 AMJames Fellows Yates
04/30/2026, 8:33 AMJames Fellows Yates
04/30/2026, 8:33 AMJames Fellows Yates
04/30/2026, 8:33 AMJames Fellows Yates
04/30/2026, 8:33 AMJim Downie
04/30/2026, 8:34 AMJim Downie
04/30/2026, 8:35 AMJim Downie
04/30/2026, 8:35 AMJim Downie
04/30/2026, 9:00 AMch_prepped_aa_fastas_renamed = SEQKIT_BATCHRENAME.out.fastx
.map { _meta, fasta -> [[id: params.dbname], fasta] }
.groupTuple()
.map { meta, fasta ->
[meta, fasta.flatten()]
}James Fellows Yates
04/30/2026, 9:01 AMJames Fellows Yates
04/30/2026, 9:01 AMfasta element be independent at this point 🤔James Fellows Yates
04/30/2026, 9:02 AMJames Fellows Yates
04/30/2026, 9:49 AMSummary
The java.util.ConcurrentModificationException errors in the nf-core/createtaxdb pipeline are caused by concurrent access to shared collections and file staging conflicts. Here's what I found and fixed:
Root Causes:
Complex channel operations with groupTuple(), map(), and join() creating race conditions when multiple processes access the same data structures
Shared staging directories where multiple processes try to stage files to the same location simultaneously
Lack of process-level synchronization for critical operations
Fixes Applied:
Process Synchronization: Added maxForks = 1 for FIND processes to serialize them, and maxForks = 2 for MALT_BUILD/METACACHE_BUILD to limit concurrency
Unique Staging Directories: Modified staging paths to use ${task.index} to ensure each task gets its own staging directory
Retry Logic: Added automatic retry mechanisms with errorStrategy and maxRetries = 3 for all problematic processes
Error Handling: Improved error handling to gracefully handle and retry failed tasks
Expected Results:
Elimination of ConcurrentModificationException errors
Improved reliability through automatic retries
Maintained functionality with minimal performance impact
Better resource management through controlled concurrency
The fixes maintain the original pipeline functionality while addressing the concurrency issues that were causing the sporadic failures. The FIND processes will now run sequentially (preventing race conditions), and the build processes use unique staging directories to avoid file conflicts.
I'm done.
I don't know WHERE it's applied these fixes though 😅James Fellows Yates
04/30/2026, 11:33 AMmaxForks = 1 for everything does seem to fix this though 😅James Fellows Yates
04/30/2026, 11:48 AMJames Fellows Yates
04/30/2026, 11:50 AMch_prepped_dna_fastas bit here:
// Unbatch the unzipped files for rematching with metadata
ch_prepped_dna_fastas_gunzipped = ch_prepped_dna_batches
.flatMap { _meta, batch -> batch }
.map { fasta -> [fasta.getName(), fasta] }
// Match metadata back to the prepped DNA fastas with an inner join
ch_prepped_dna_fastas_ungrouped = ch_prepped_dna_fastas_gunzipped
.join(ch_dna_refs_for_rematching, failOnMismatch: true, failOnDuplicate: true)
.map { _fasta_name, fasta, meta -> [meta, fasta] }
// Prepare for making the mega file
ch_prepped_dna_fastas = ch_prepped_dna_fastas_ungrouped
.map { _meta, fasta ->
[[id: params.dbname], fasta]
}
.groupTuple()James Fellows Yates
04/30/2026, 11:50 AMMaxime Garcia
04/30/2026, 12:02 PMMaxime Garcia
04/30/2026, 12:03 PMJames Fellows Yates
04/30/2026, 12:03 PMJames Fellows Yates
04/30/2026, 12:03 PMConcurrentModificationException, with processes trying to pull the same thingJames Fellows Yates
04/30/2026, 12:03 PMMaxime Garcia
04/30/2026, 12:04 PMJames Fellows Yates
04/30/2026, 12:04 PMMaxime Garcia
04/30/2026, 12:04 PMJames Fellows Yates
04/30/2026, 12:04 PMJames Fellows Yates
04/30/2026, 12:04 PMJames Fellows Yates
04/30/2026, 12:05 PMMaxime Garcia
04/30/2026, 12:05 PMJames Fellows Yates
04/30/2026, 12:05 PMJames Fellows Yates
04/30/2026, 12:05 PMJames Fellows Yates
04/30/2026, 12:05 PMJames Fellows Yates
04/30/2026, 12:06 PMMaxime Garcia
04/30/2026, 12:06 PMJames Fellows Yates
04/30/2026, 12:06 PMUnique Staging Directories: Modified staging paths to use ${task.index} to ensure each task gets its own staging directory
But that sounds dodgy to meJim Downie
04/30/2026, 12:07 PMJames Fellows Yates
04/30/2026, 12:07 PMMake a copy of the input channel, and try to join it with the output of 1 of these process, and use it as input for all your other processesWouldn't that essentially make the whole thing linear?
James Fellows Yates
04/30/2026, 12:07 PMIs it explicitly always the FIND_CONCATENATE processes that fail?Most commonly, but that's what I just realised: METACACHE and MALT and the others that it occasioanlly comes up all share the same input channel
James Fellows Yates
04/30/2026, 12:08 PMJim Downie
04/30/2026, 12:11 PMJames Fellows Yates
04/30/2026, 12:11 PMJames Fellows Yates
04/30/2026, 12:11 PMJames Fellows Yates
04/30/2026, 12:12 PMJim Downie
04/30/2026, 12:13 PMJim Downie
04/30/2026, 12:13 PMJames Fellows Yates
04/30/2026, 12:42 PMJames Fellows Yates
04/30/2026, 12:42 PMJim Downie
04/30/2026, 12:54 PMJames Fellows Yates
04/30/2026, 1:12 PMJim Downie
04/30/2026, 1:19 PMMaxime Garcia
04/30/2026, 1:20 PM