Skip to content

Cannot parse manifest.contributors without contribution field. #6382

@robsyme

Description

@robsyme

Bug report

Expected behavior and actual behavior

Expected behavior: When a contributor in manifest.contributors omits the contribution field, Nextflow should either:

  1. Use a default value (e.g., empty list or ['contributor'])
  2. Provide a clear error message indicating the missing required field

Actual behavior: Nextflow crashes with a NullPointerException that is difficult to debug, showing only:

ERROR ~ Cannot invoke "java.util.Collection.stream()" because "

Steps to reproduce the problem

  1. Create a nextflow.config file with contributors that omit the contribution field:
manifest {
    name = "Test Workflow"
    contributors = [
        [
            name: 'John Doe',
            affiliation: 'Example University',
            orcid: 'https://orcid.org/0000-0000-0000-0000'
        ]
    ]
}

process.container = 'ubuntu:latest'
  1. Create a simple main.nf:
#!/usr/bin/env nextflow

process Dummy {
    debug true
    script:
    "echo 'Hello world!'"
}

workflow {
    Dummy()
}
  1. Run: nextflow run .

Program output

N E X T F L O W   ~  version 25.07.0-edge

ERROR ~ Cannot invoke "java.util.Collection.stream()" because "

 -- Check '.nextflow.log' file for details

Complete stack trace from .nextflow.log:

java.lang.NullPointerException: Cannot invoke "java.util.Collection.stream()" because "
	at nextflow.config.Manifest$Contributor.<init>(Manifest.groovy:211)
	at nextflow.config.Manifest$_parseContributors_lambda1.doCall(Manifest.groovy:170)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
	at org.codehaus.groovy.runtime.StreamGroovyMethods.toList(StreamGroovyMethods.java:463)
	at nextflow.config.Manifest.parseContributors(Manifest.groovy:169)
	at nextflow.config.Manifest.<init>(Manifest.groovy:146)
	at nextflow.scm.AssetManager.getManifest0(AssetManager.groovy:469)
	at nextflow.scm.AssetManager.memoizedMethodPriv$getManifest(AssetManager.groovy:441)
	...
	at nextflow.cli.CmdRun.run(CmdRun.groovy:326)
	at nextflow.cli.Launcher.run(Launcher.groovy:513)
	at nextflow.cli.Launcher.main(Launcher.groovy:673)

Environment

  • Nextflow version: 25.07.0-edge build 5954
  • Java version: OpenJDK 64-Bit Server VM 21.0.8
  • Operating system: macOS 15.6.1
  • Bash version: GNU bash, version 3.2.57(1)-release (arm64-apple-darwin24)

Additional context

Root cause: In Manifest.groovy line 211, the Contributor constructor attempts to call .stream() on opts.contribution without null-checking:

contribution = (opts.contribution as List<String>).stream()
    .map(c -> ContributionType.valueOf(c.toUpperCase()))
    .sorted()
    .toList()

When opts.contribution is null (i.e., the field is omitted), (null as List<String>) results in null, and calling .stream() on null throws the NPE.

Documentation inconsistency: The documentation lists contribution as a supported field but doesn't clearly indicate it's required. However, the code implementation makes it functionally mandatory.

Suggested fix: Add null-safety handling:

contribution = opts.contribution ? 
    (opts.contribution as List<String>).stream()
        .map(c -> ContributionType.valueOf(c.toUpperCase()))
        .sorted()
        .toList() : 
    []

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions