Plugin using getOutputsByType broken in nextflow v26

I have a custom nextflow plugin that uses TaskRun.getOutputsByType(ValueOutParam) and TaskRun.getOutputsByType(FileOutParam) to get outputs. This seems to be broken after updating to nextflow 26.01.1-edge (using strict syntax and nextflow.preview.types = true). Is that expected? If so, is there a new syntax i should be using? Or should i dig more deeply to see if it’s something else that’s broken?

@bentsherman do you have any ideas about this?

Hi,

Thanks for reporting this. The behaviour you’re seeing is a side effect of the typed processes work that landed in 26.01-edge (nextflow-io/nextflow#6368) and is opted into by nextflow.preview.types = true. It’s not strictly a bug in getOutputsByType, but it does make the v1 OutParam API a dead end for typed processes.

Under the legacy DSL, TaskRun.outputs is a Map<OutParam,Object> keyed by the v1 param classes from nextflow.script.params.*FileOutParam, ValueOutParam, EnvOutParam, and friends. getOutputsByType(FileOutParam) filters that map by it.key.class.

For typed processes, output declarations are modelled by a parallel set of classes in nextflow.script.params.v2 (e.g. ProcessFileOutput). Resolution runs through TaskOutputResolver and binding through TaskProcessor.bindOutputsV2, which iterates configV2().getOutputs().getParams() and reads task.outputs[param] where param is a typed output, not a FileOutParam.

So under typed processes the keys in task.outputs are never subclasses of FileOutParam/ValueOutParam, and getOutputsByType(FileOutParam) returns an empty map. Internal call sites that still need the v1 view (e.g. the publish helper in TaskProcessor) have been split into V1/V2 variants; plugin code outside the tree hasn’t had that migration applied.

Suggestions
Short-term, you can branch on the process config and read typed outputs via the v2 API:

    if (task.processor.config instanceof ProcessConfigV2) {
        def cfg = (ProcessConfigV2) task.processor.config
        for (def param : cfg.getOutputs().getParams()) {
            def value = task.outputs[param]
            // inspect param / value here
        }
    } else {
        // existing v1 path
        task.getOutputsByType(FileOutParam).each { ... }
    }

Caveat: ProcessConfigV2 and the nextflow.script.params.v2 classes are not yet documented as a stable plugin API, so this is best treated as a stop-gap until there’s an explicit plugin-facing replacement. @bentsherman would be the right person to confirm the supported migration path.

Rob has the right idea. Typed processes have a different runtime model for inputs and outputs, so plugins will need to handle legacy/typed processes separately.

You can look at TaskProcessor in the Nextflow runtime to see some examples. I will also update nf-prov at some point to illustrate this.

This will probably remain a rough edge for a while. I might be able to eventually re-unify everything by compiling legacy processes into the typed model under the hood. But for now I think simply handling both cases is your best bet.