Skip to content

fix: DSL2 optional-output syntax for Nextflow 25.x + clamp version#10

Merged
jspaezp merged 1 commit into
masterfrom
fix/nextflow-25-optional-output
Jul 6, 2026
Merged

fix: DSL2 optional-output syntax for Nextflow 25.x + clamp version#10
jspaezp merged 1 commit into
masterfrom
fix/nextflow-25-optional-output

Conversation

@jspaezp

@jspaezp jspaezp commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Root cause

Our AWS Batch runner image was bumped to nextflow/nextflow:25.10.4 (required so env() works in the SCM config). On 25.x, Nextflow parses the bareword DSL2 process-output form

path "<glob>" optional true

as path("<glob>").optional(true). The inner call now returns null, so .optional(true) throws at script-load / include time:

java.lang.NullPointerException: Cannot invoke method optional() on null object
  at ...BaseScript.process(BaseScript.groovy:136)

Because this fires while parsing an include (not at runtime), a single offending module aborts the entire pipeline before any workflow runs — even modules for paths we never execute. Confirmed originally on rev de14f523: first failure at modules/local/msstatstmt/main.nf (path "*.pdf" optional true), which killed a DIA/LFQ job that never intended to touch TMT.

It worked before only because the old runner ran an older Nextflow.

Fix

Convert every bareword occurrence to the modern comma+colon form (, optional: true). Lines already using , optional: true (multiqc, pmultiqc, proteinquantifier) were left alone.

File Line(s) Change
modules/local/msstats/main.nf 18 path "*.pdf" optional truepath "*.pdf", optional: true
modules/local/msstatstmt/main.nf 18 path "*.pdf" optional truepath "*.pdf", optional: true
modules/local/openms/proteomicslfq/main.nf 20–27 8 outputs ... emit: X optional true... emit: X, optional: true
nextflow.config 446 nextflowVersion = '!>=23.04.0'nextflowVersion = '!>=25.04.0'

The version clamp matches the runner; ! enforces it.

Verification

Under Nextflow 25.10.4, nextflow inspect main.nf -profile test,docker loads the full include graph and resolves cleanly — no optional() NPE. 41 processes resolved, including the previously-broken MSSTATS, MSSTATSTMT, PROTEOMICSLFQ, plus all TMT/DIA-NN modules.

Direct before/after on the offending module (25.10.4):

=== BROKEN (git HEAD) ===
ERROR ~ Cannot invoke method optional() on null object
=== FIXED (this branch) ===
Launching `repro_fixed.nf` [gloomy_murdock] DSL2 - revision: 6e528479d6   # clean, no NPE

nextflow inspect output (head):

{
    "processes": [
        { "name": "SILICOLIBRARYGENERATION", "container": "docker.io/biocontainers/diann:v1.8.1_cv1" },
        { "name": "SEARCHENGINESAGE", "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1" },
        ...
        { "name": "MSSTATS", ... },
        { "name": "PROTEOMICSLFQ", ... },
        { "name": "MSSTATSTMT", ... },
        { "name": "DIANNSUMMARY", "container": "docker.io/biocontainers/diann:v1.8.1_cv1" }
    ]
}

exit=0, zero errors/exceptions in stderr.

Scope

Fork-only — not pushed upstream (nf-core / bigbio). This fork carries DIA-NN in-workflow, which upstream dropped.

Nextflow 25.x parses the bareword process-output form
`path "<glob>" optional true` as `path("<glob>").optional(true)`,
where the inner call returns null, throwing at script-load/include
time:

  java.lang.NullPointerException: Cannot invoke method optional() on null object
    at BaseScript.process(BaseScript.groovy:136)

Because this fires while parsing an include, one offending module
aborts the whole pipeline before any workflow runs — even modules
whose paths are never executed.

Convert every bareword occurrence to the modern comma+colon form
(`, optional: true`) and clamp the required Nextflow version to the
runner (25.04+).

Files:
- modules/local/msstats/main.nf:18
- modules/local/msstatstmt/main.nf:18
- modules/local/openms/proteomicslfq/main.nf:20-27 (8 outputs)
- nextflow.config:446 nextflowVersion '!>=23.04.0' -> '!>=25.04.0'

Verified with `nextflow inspect main.nf -profile test,docker` on
Nextflow 25.10.4: full include graph parses clean (41 processes
resolved, no optional() NPE).
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Python linting (black) is failing

To keep the code consistent with lots of contributors, we run automated code consistency checks.
To fix this CI test, please run:

  • Install black: pip install black
  • Fix formatting errors in your pipeline: black .

Once you push these changes the test should pass, and you can hide this comment 👍

We highly recommend setting up Black in your code editor so that this formatting is done automatically on save. Ask about it on Slack for help!

Thanks again for your contribution!

@jspaezp jspaezp merged commit 8d21a05 into master Jul 6, 2026
3 of 18 checks passed
@jspaezp jspaezp deleted the fix/nextflow-25-optional-output branch July 6, 2026 03:49
@jspaezp

jspaezp commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author
 nextflow -version

      N E X T F L O W
      version 26.04.4 build 12445
      created 17-06-2026 16:30 UTC (09:30 PDT)
      cite doi:10.1038/nbt.3820
      http://nextflow.io
NXF_SYNTAX_PARSER=v1 nextflow inspect main.nf -profile test,docker
{
    "processes": [
        {
            "name": "SILICOLIBRARYGENERATION",
            "container": "docker.io/biocontainers/diann:v1.8.1_cv1"
        },
        {
            "name": "SEARCHENGINESAGE",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "DECOMPRESS",
            "container": "quay.io/biocontainers/mulled-v2-796b0610595ad1995b121d0b85375902097b78d4:a3a3220eb9ee55710d743438b2ab9092867c98c6-0"
        },
        {
            "name": "IDCONFLICTRESOLVER",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "MSSTATS",
            "container": "quay.io/biocontainers/bioconductor-msstats:4.8.3--r43hf17093f_0"
        },
        {
            "name": "MZMLINDEXING",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "PROTEOMICSLFQ",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "SDRFPARSING",
            "container": "quay.io/biocontainers/sdrf-pipelines:0.0.24--pyhdfd78af_0"
        },
        {
            "name": "MSSTATSTMT",
            "container": "quay.io/biocontainers/bioconductor-msstatstmt:2.8.0--r43hdfd78af_0"
        },
        {
            "name": "IDSCORESWITCHER",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "PREPROCESS_EXPDESIGN",
            "container": "quay.io/biocontainers/sdrf-pipelines:0.0.24--pyhdfd78af_0"
        },
        {
            "name": "DECOYDATABASE",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "TDF2MZML",
            "container": "docker.io/mfreitas/tdf2mzml:latest"
        },
        {
            "name": "PROTEININFERENCE",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "MZMLSTATISTICS",
            "container": "quay.io/biocontainers/pyopenms:2.8.0--py38hd8d5640_1"
        },
        {
            "name": "FALSEDISCOVERYRATE",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "OPENMSPEAKPICKER",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "EXTRACTPSMFEATURES",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "MSSTATSCONVERTER",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "PMULTIQC",
            "container": "quay.io/biocontainers/pmultiqc:0.0.23--pyhdfd78af_0"
        },
        {
            "name": "IDMAPPER",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "ASSEMBLE_EMPIRICAL_LIBRARY",
            "container": "docker.io/biocontainers/diann:v1.8.1_cv1"
        },
        {
            "name": "SAMPLESHEET_CHECK",
            "container": "quay.io/biocontainers/sdrf-pipelines:0.0.24--pyhdfd78af_0"
        },
        {
            "name": "DIANN_PRELIMINARY_ANALYSIS",
            "container": "docker.io/biocontainers/diann:v1.8.1_cv1"
        },
        {
            "name": "IDPEP",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "IDFILTER",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "INDIVIDUAL_FINAL_ANALYSIS",
            "container": "docker.io/biocontainers/diann:v1.8.1_cv1"
        },
        {
            "name": "THERMORAWFILEPARSER",
            "container": "quay.io/biocontainers/thermorawfileparser:1.3.4--ha8f3691_0"
        },
        {
            "name": "GENERATE_DIANN_CFG",
            "container": "quay.io/biocontainers/sdrf-pipelines:0.0.22--pyhdfd78af_0"
        },
        {
            "name": "PROTEINQUANTIFIER",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "ISOBARICANALYZER",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "SEARCHENGINECOMET",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "DIANNCONVERT",
            "container": "quay.io/biocontainers/pmultiqc:0.0.22--pyhdfd78af_0"
        },
        {
            "name": "CONSENSUSID",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "EPIFANY",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "LUCIPHORADAPTER",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "CUSTOM_DUMPSOFTWAREVERSIONS",
            "container": "quay.io/biocontainers/multiqc:1.14--pyhdfd78af_0"
        },
        {
            "name": "PERCOLATOR",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "FILEMERGE",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "SEARCHENGINEMSGF",
            "container": "quay.io/biocontainers/openms-thirdparty:3.1.0--h9ee0642_1"
        },
        {
            "name": "DIANNSUMMARY",
            "container": "docker.io/biocontainers/diann:v1.8.1_cv1"
        }
    ]
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant