Nextflow documentation is migrating

Nextflow documentation is being migrated to docs.seqera.io/nextflow. This site will remain available throughout the migration.

Migrating to 26.04 (preview)

This page summarizes the upcoming changes in Nextflow 26.04, which will be released in April 2026.

Note

This page is a work in progress and will be updated as features are finalized. It should not be considered complete until the 26.04 release.

New features

Module system

Nextflow now has native support for publishing, installing, running, and including remote modules using the Nextflow registry.

The new module command can be used to work with remote modules:

# Run a module directly
nextflow module run nf-core/fastqc --meta.id 1 --reads sample1.fastq

# Search for modules in registry
nextflow module search bwa

# Get info about a module
nextflow module info nf-core/bwa/mem

# Install a module
nextflow module install nf-core/bwa/mem

Remotes modules are installed into the modules directory of your project. They can be included in scripts by name instead of relative path:

// before
include { BWA_MEM } from '../../../modules/nf-core/bwa/mem'

// after
include { BWA_MEM } from 'nf-core/bwa/mem'

Note

All nf-core modules are automatically synced to the registry from GitHub. They are available as nf-core/<name> as shown above.

See Registry-based modules and the module command reference for details.

Record types

Records are a new data structure for modeling composite data. They serve as an alternative to tuples – whereas tuple elements must be accessed by index, record fields are accessed by name. This allows you to model data with meaningful names instead of keeping track of how tuple elements are ordered.

A record can be created using the record() function:

sample = record(
    id: '1',
    fastq_1: file('1_1.fastq'),
    fastq_2: file('1_2.fastq')
)

println sample.id
println sample.foo  // error: unrecognized property `foo`

Record types are a way to define custom types for validating records:

record Sample {
    id: String
    fastq_1: Path
    fastq_2: Path?
}

While records created with the record() function can have any set of fields, record types can be used to specify a minimum set of requirements in a particular context, such as a process, function, or workflow:

def hello(sample: Sample) {
    println "Hello sample ${sample.id}!"
}

workflow {
    sample1 = record(id: '1', fastq_2: file('1_2.fastq'))
    hello(sample1) // error: `sample1` is missing `fastq_1` field required by Sample

    sample2 = record(id: '1', fastq_1: file('1_1.fastq'))
    hello(sample2) // ok

    sample3 = record(id: '1', single_end: true, fastq_1: file('1_1.fastq'))
    hello(sample3) // also ok
}

See Records for details. See Migrating to static typing for more information about migrating from tuples to records.

Static typing (preview)

Note

Typed processes and typed workflows require the nextflow.preview.types feature flag to be enabled in every script that uses them.

Nextflow 26.04 brings full support for static typing with typed processes and typed workflows.

Typed processes can now declare record inputs and outputs:

nextflow.preview.types = true

process FASTQC {
    input:
    record(
        id: String,
        fastq_1: Path,
        fastq_2: Path
    )

    output:
    record(
        id: id,
        fastqc: file('fastqc_logs')
    )

    script:
    // ...
}

Typed workflows can declare typed inputs and outputs, and provide first-class support for static typing in dataflow logic:

nextflow.preview.types = true

workflow RNASEQ {
    take:
    read_pairs_ch: Channel<Sample>
    transcriptome: Path

    main:
    index = INDEX(transcriptome)
    fastqc_ch = FASTQC(read_pairs_ch)
    quant_ch = QUANT(read_pairs_ch, index)
    samples_ch = fastqc_ch.join(quant_ch, by: 'id')

    emit:
    samples: Channel<AlignedSample> = samples_ch
}

record Sample { /* ... */ }
record AlignedSample { /* ... */ }

Several operators have been extended to support static typing and records:

  • combine can now combine records or tuples

  • groupBy can group channel values while being statically typed (replaces groupTuple)

  • join can now join records by matching field

Breaking changes from the first preview:

  • The syntax for process tuple inputs has been updated:

    // 25.10
    input:
    (id, fastq_1, fastq_2): Tuple<String,Path,Path>
    
    // 26.04
    input:
    tuple(id: String, fastq_1: Path, fastq_2: Path)
    
  • The method signature for the stageAs directive was changed from (filePattern, value) to (value, filePattern).

  • The nextflow.preview.types feature flag must be enabled in order to use type annotations in workflow takes/emits.

See Migrating to static typing for more information about migrating to static typing. See Using operators with static typing for best practices on using operators with static typing.

Enhancements

Strict syntax parser enabled by default

The strict syntax parser is now enabled by default. This change brings the rich error checking of nextflow lint to nextflow run, and makes it easier to adopt new language features.

The legacy parser can be re-enabled by setting the NXF_SYNTAX_PARSER environment variable to v1.

Agent logging mode

Nextflow prints logs in an agent-friendly format when enabled via NXF_AGENT_MODE=1:

$ NXF_AGENT_MODE=1 nextflow run [...]
[PIPELINE] nf-core/rnaseq 3.14.0 | profile=test,docker
[WORKDIR] /path/to/work
[PROCESS b8/623fc3] sayHello (3)
[PROCESS 5f/761e51] sayHello (2)

[WARN] Task runtime metrics are not reported when using macOS

[ERROR] FASTQC (sample_1)
exit: 127
cmd: fastqc --version
stderr: bash: fastqc: command not found
workdir: /path/to/work/ab/123456

[SUCCESS] completed=10 failed=0 cached=5

Agent mode provides minimal structured logging for efficient token usage. It is ideal when using agents to run and debug Nextflow runs.

Multi-revision checkout for pipelines

Nextflow now checks out pipelines separately by revision when running remote pipelines, allowing you to run multiple revisions of a pipeline at the same time.

Nextflow uses the default branch specified by the Git repository when no revision is specified, instead of defaulting to the master branch. Since each revision is checked out separately, using a specific revision doesn’t prevent the use of the default branch on subsequent runs.

Because of this update, the manifest.defaultBranch config option is no longer needed.

Load collection-type params automatically from files

When using the params block, collection-type parameters such as List<Record> can be loaded automatically from a CSV, JSON, or YAML file. This feature simplifies the loading of samplesheet inputs and allows a pipeline to support multiple structured data formats.

See Typed parameters for details. See Migrating to static typing for a migration example.

Print workflow outputs on run completion

Nextflow prints a summary of the workflow outputs at the end of a run, when the output block is defined.

For example, given the following output block:

workflow {
    // ...
}

output {
    samples {
        path { sample -> "${sample.id}" }
        index {
            path 'samples.csv'
        }
    }

    multiqc_report {
        path 'multiqc_report.html'
    }
}

Nextflow prints the following summary:

$ nextflow -q run main.nf
Outputs:

  /path/to/results

  samples: samples.csv

  multiqc_report: multiqc_report.html

You can specify -output-format json to produce JSON output instead:

$ nextflow -q run main.nf -output-format json
{
    "samples": "/path/to/results/samples.csv",
    "multiqc_report": "/path/to/results/multiqc_report.html"
}

The module run command prints a summary of the module outputs:

$ nextflow -q module run nf-core/fastqc --meta.id 1 --reads sample1.fastq -output-format json
{
    "html": [
        {
            "id": "SRR6357070_1"
        },
        "/path/to/results/SRR6357070_1_fastqc.html"
    ],
    "zip": [
        {
            "id": "SRR6357070_1"
        },
        "/path/to/results/SRR6357070_1_fastqc.zip"
    ]
}

See the run command reference for details.

New -project-dir option for lint command

The lint command now has a -project-dir option, which can be used to specify the project root when linting files.

For example, given the following project structure:

├── lib
│   └── Utils.groovy
├── modules
│   └── nf-core
│       └── fastqc
│           ├── main.nf
│           └── ...
├── workflows
│   └── rnaseq.nf
├── main.nf
└── nextflow.config

You can specify -project-dir when linting from a location other than the project root:

cd workflows
nextflow lint -project-dir ../ rnaseq.nf

This option allows the linter to resolve remote module includes and Groovy code in the lib directory:

// workflows/rnaseq.nf

include { FASTQC } from 'nf-core/fastqc'

workflow RNASEQ {
    // ...

    Utils.validateInput( /* ... */ )

    // ...
}

See the lint command reference for details.

Breaking changes

  • The strict syntax parser is now enabled by default. The legacy parser can be enabled by setting the NXF_SYNTAX_PARSER environment variable to v1.

Deprecations

  • The nextflow.enable.strict feature flag is deprecated. It is not needed when strict syntax is enabled.

  • The manifest.defaultBranch config option is deprecated. Nextflow can automatically detect the default branch when using a remote pipeline.

  • The Path listFiles() method is deprecated. Use listDirectory() instead.

  • Several operators have been deprecated. See Operators (legacy) for details.

Miscellaneous

  • New config option: aws.batch.forceGlacierTransfer

  • New config option: executor.onlyJobState

  • New config option: google.batch.installOpsAgent

  • New config option: google.batch.logsPath

  • New config option: wave.build.conda.baseImage

  • New config option: wave.build.template

  • New standard library function: listDirectory()

  • Support Java 26