<p>Channel names must consist only alphanumeric characters including underscores. Your channel called 'plink-data' contains a hyphen. This is problematic because it is interpreted as a minus() operation to remove 'data' from 'plink'. You get a NullPointerException since 'plink' hasn't been defined. You can test this easily with the following example:</p>
<pre><code>Channel
    .of(1..23, 'X', 'Y')
    .set { chr-names }

chr-names.view()
</code></pre>
<p>Results:</p>
<pre><code>Cannot invoke method minus() on null object
</code></pre>
<p>The solution is to just use an underscore instead of a hyphen:</p>
<pre><code>Channel
    .of(1..23, 'X', 'Y')
    .set { chr_names }

chr_names.view()
</code></pre>
<hr />
<p><strong>Follow-up issues:</strong></p>
<p>I think if you want to use the bfiles plink option (and I think this is reasonable), I think it makes the most sense to just keep your bfiles in a tuple:</p>
<pre><code>Channel
    .fromFilePairs( &quot;${params.input_dir}/*.{bed,bim,fam}&quot;, size: 3 )
    .set { plink_data }


process test1{

    publishDir params.publish_dir

    module 'plink'

    input:
    tuple val(sample_name), path(bfiles) from plink_data

    output:
    tuple val(&quot;<span class="math-container">${sample_name}-t1"), path("$</span>{sample_name}-t1.{bed,bim,fam}&quot;) into test1_results

    &quot;&quot;&quot;
    plink \\
        --bfile &quot;<span class="math-container">${sample_name}" \\
        --maf 0.05 \\
        --make-bed \\
        --out "$</span>{sample_name}-t1&quot;
    &quot;&quot;&quot;
}

process test2{

    publishDir params.publish_dir

    module 'plink'

    input:
    tuple val(sample_name), path(bfiles) from test1_results

    output:
    tuple val(&quot;<span class="math-container">${sample_name}-t2"), path("$</span>{sample_name}-t2.{bed,bim,fam}&quot;) into test2_results

    &quot;&quot;&quot;
    plink \\
        --bfile &quot;<span class="math-container">${sample_name}" \\
        --maf 0.01 \\
        --make-bed \\
        --out "$</span>{sample_name}-t2&quot;
    &quot;&quot;&quot;
}
</code></pre>
<p>If you need to reference each bfile separately, you could just unpack the tuple and reference each file accordingly:</p>
<pre><code>Channel
    .fromFilePairs( &quot;${params.input_dir}/*.{bed,bim,fam}&quot;, size: 3 )
    .map { group_key, files -&gt; tuple( group_key, *files ) }
    .set { plink_data }


process test1{

    publishDir params.publish_dir

    module 'plink'

    input:
    tuple val(sample_name), path(bed), path(bim), path(fam) from plink_data

    output:
    tuple val(&quot;<span class="math-container">${sample_name}-t1"), path("$</span>{sample_name}-t1.{bed,bim,fam}&quot;) into test1_results

    &quot;&quot;&quot;
    plink \\
        --bed &quot;<span class="math-container">${bed}" \\
        --bim "$</span>{bim}&quot; \\
        --fam &quot;<span class="math-container">${fam}" \\
        --maf 0.05 \\
        --make-bed \\
        --out "$</span>{sample_name}-t1&quot;
    &quot;&quot;&quot;
}

process test2{

    publishDir params.publish_dir

    module 'plink'

    input:
    tuple val(sample_name), path(bed), path(bim), path(fam) from test1_results

    output:
    tuple val(&quot;<span class="math-container">${sample_name}-t2"), path("$</span>{sample_name}-t2.{bed,bim,fam}&quot;) into test2_results

    &quot;&quot;&quot;
    plink \\
        --bed &quot;<span class="math-container">${bed}" \\
        --bim "$</span>{bim}&quot; \\
        --fam &quot;<span class="math-container">${fam}" \\
        --maf 0.01 \\
        --make-bed \\
        --out "$</span>{sample_name}-t2&quot;
    &quot;&quot;&quot;
}
</code></pre>
<p>Note that in the first example, <code>bfiles</code> could be replaced with <code>&quot;*&quot;</code> since no reference is made to the tuple of bfiles anyway. Also note that the list of files produced using the <a href="https://www.nextflow.io/docs/latest/channel.html#fromfilepairs" rel="nofollow noreferrer">fromFilesPairs operator</a> are returned in lexicographic order.</p>

CC BY-SA 4.0
2021-03-19T16:50:31.367Z
Thanks @Steve, I modified the code but getting a new issue:
'process test1{
publishDir params.publish
input:
set t1, file(plk1) from data
output: set t2, file "${t2}.{bed,fam.bim}" into test1_results
script:
"""
plink --bfile $t1 --maf 0.05 --make-bed --out ${t2}
"""
'
the error is: no such variable: t2
I have 3 files (.bed,.bim,.fam), process test1 will generate another 3 (.bed,.bim,.fam) files which will be used in the next process.
How could I declare t1,t2,t3 etc (the inputs and outputs) correctly?
zillur rahman
CC BY-SA 4.0
2021-03-20T03:28:07.933Z
No worries @zillurrahman, I have added some example code to show how you could declare your inputs and outputs. The inputs could just be a tuple of bfiles or each file could be referenced separately. I haven't used plink before and have only had a (very) quick read of the docs, so there may be some more issues. Hopefully it's enough to get you started.
Steve
CC BY-SA 4.0
2021-03-20T09:35:06.340Z
Thanks a lot @Steve. It works as I expected! One thing, plink also generate a log file, I need this as one of the outputs but the log will not be used in the next process. Now I am adding more processes in the script, I will get back to you if I got stuck again.
zillur rahman
CC BY-SA 4.0
2021-03-20T11:19:44.783Z
So for Nextflow to be able to publish a file using the publishDir directive, it (the file) needs to be referenced in your process' output declaration block somehow. If it's not required by any downstream process, you can just add another output channel, for example: `path("${sample_name.log}") into test1_logs`. Please let me know if that doesn't make sense. Cheers.
Steve
CC BY-SA 4.0
2021-03-20T11:57:13.890Z
Thank you @Steve, It seems I can declare multiple output, which is very much useful for my pipeline. Just one thing, if I  'path("${sample_name.log}") into test1_logs' it shows 'No such variable: log'.
zillur rahman
CC BY-SA 4.0
2021-03-20T14:18:13.000Z
Erp there's a typo in there.. you'll need: `path("${sample_name}.log") into test1_logs` if your log's filename fits that format. Whether it does or not, you'll need to check. HTH.
Steve
CC BY-SA 4.0
2021-03-20T16:35:51.960Z
Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/121077/discussion-between-zillur-rahman-and-steve).
zillur rahman
CC BY-SA 4.0
2021-03-20T17:26:35.150Z
Thanks @Steve, I also tried it. If I use path("${sample_name}.log") , it shows error execution prosess; caused by missing output files. If I use path("${sample_name}".log) , it shows no such variable: log
zillur rahman
CC BY-SA 4.0
2021-03-21T03:09:00.397Z
What's the name of your log file? I haven't run plink before, so I just used `"${sample_name}.log"` as an example. If the name of the log file is 'plink.log' then you'd use: `path("plink.log") into test1_logs` in your output declaration.
Steve
CC BY-SA 4.0
2021-03-21T08:31:49.843Z
Thanks @Steve, The final output.log is the log file. Sorry I failed to clarify. However, path("${sample_name}-t1.log") into test1_logs works as I expected! Thank a lot again.
zillur rahman
CC BY-SA 4.0
2021-03-19T13:33:33.857Z
2021-03-20T03:21:14.817Z
2021-03-20T03:21:14.817Z
Steve
<p>Hi I was trying to use plink in nextflow and getting the error mentioned in the subject. Here is my code, any help what I am missing. I am new in nextflow, it was ok when input was a single file, but for grouped files, I am getting lost.</p>
<pre><code>params.dir='data/'
params.publish=&quot;output/&quot;
Channel
.fromFilePairs(&quot;${params.dir}*.{bed,fam,bim}&quot;,size:3){file -&gt; file.baseName}
.set {plink-data}
    
process test1{
publishDir params.publish
input:
set t1,file(plk1) from plink-data
output:
file &quot;<span class="math-container">${t1}.{bed,fam,bim}" into test1_results
script:
output_file = "$</span>{t1}&quot;
base = plk1[0].baseName
&quot;&quot;&quot;
module load plink
plink --bfile <span class="math-container">$t1 --maf 0.05 --make-bed --out $</span>{output_file}
&quot;&quot;&quot;
}
process test2{
publishDir params.publish
input:
set file(bed), file(fam), file(bim) from test1_results.collect()
output:
set t2,file '<span class="math-container">${plk2}.{bed,fam,bim}' into test2_results
script:
output_file = "{t2}"
base = plk2[0].baseName
"""
plink --bfile $</span>t2 --maf 0.01 --make-bed --out ${output_file}
&quot;&quot;&quot;
}
</code></pre>

<nextflow>
Nextflow error: can not invoke method minus () on null object
# Nextflow error: can not invoke method minus () on null object

(Asked by: username_0 on 2021-03-19)

Hi I was trying to use plink in nextflow and getting the error mentioned in the subject. Here is my code, any help what I am missing. I am new in nextflow, it was ok when input was a single file, but for grouped files, I am getting lost.
params.dir='data/'
params.publish="output/"
Channel
.fromFilePairs("${params.dir}*.{bed,fam,bim}",size:3){file -> file.baseName}
.set {plink-data}
    
process test1{
publishDir params.publish
input:
set t1,file(plk1) from plink-data
output:
file "${t1}.{bed,fam,bim}" into test1_results
script:
output_file = "${t1}"
base = plk1[0].baseName
"""
module load plink
plink --bfile $t1 --maf 0.05 --make-bed --out ${output_file}
"""
}
process test2{
publishDir params.publish
input:
set file(bed), file(fam), file(bim) from test1_results.collect()
output:
set t2,file '${plk2}.{bed,fam,bim}' into test2_results
script:
output_file = "{t2}"
base = plk2[0].baseName
"""
plink --bfile $t2 --maf 0.01 --make-bed --out ${output_file}
"""
}

**Tags:** nextflow

---

## 1 answers

### Answer by username_1 on 2021-03-19. Score: 2 | Accepted answer

Channel names must consist only alphanumeric characters including underscores. Your channel called 'plink-data' contains a hyphen. This is problematic because it is interpreted as a minus() operation to remove 'data' from 'plink'. You get a NullPointerException since 'plink' hasn't been defined. You can test this easily with the following example:
Channel
    .of(1..23, 'X', 'Y')
    .set { chr-names }

chr-names.view()

Results:
Cannot invoke method minus() on null object

The solution is to just use an underscore instead of a hyphen:
Channel
    .of(1..23, 'X', 'Y')
    .set { chr_names }

chr_names.view()


Follow-up issues:
I think if you want to use the bfiles plink option (and I think this is reasonable), I think it makes the most sense to just keep your bfiles in a tuple:
Channel
    .fromFilePairs( "${params.input_dir}/*.{bed,bim,fam}", size: 3 )
    .set { plink_data }


process test1{

    publishDir params.publish_dir

    module 'plink'

    input:
    tuple val(sample_name), path(bfiles) from plink_data

    output:
    tuple val("${sample_name}-t1"), path("${sample_name}-t1.{bed,bim,fam}") into test1_results

    """
    plink \\
        --bfile "${sample_name}" \\
        --maf 0.05 \\
        --make-bed \\
        --out "${sample_name}-t1"
    """
}

process test2{

    publishDir params.publish_dir

    module 'plink'

    input:
    tuple val(sample_name), path(bfiles) from test1_results

    output:
    tuple val("${sample_name}-t2"), path("${sample_name}-t2.{bed,bim,fam}") into test2_results

    """
    plink \\
        --bfile "${sample_name}" \\
        --maf 0.01 \\
        --make-bed \\
        --out "${sample_name}-t2"
    """
}

If you need to reference each bfile separately, you could just unpack the tuple and reference each file accordingly:
Channel
    .fromFilePairs( "${params.input_dir}/*.{bed,bim,fam}", size: 3 )
    .map { group_key, files -> tuple( group_key, *files ) }
    .set { plink_data }


process test1{

    publishDir params.publish_dir

    module 'plink'

    input:
    tuple val(sample_name), path(bed), path(bim), path(fam) from plink_data

    output:
    tuple val("${sample_name}-t1"), path("${sample_name}-t1.{bed,bim,fam}") into test1_results

    """
    plink \\
        --bed "${bed}" \\
        --bim "${bim}" \\
        --fam "${fam}" \\
        --maf 0.05 \\
        --make-bed \\
        --out "${sample_name}-t1"
    """
}

process test2{

    publishDir params.publish_dir

    module 'plink'

    input:
    tuple val(sample_name), path(bed), path(bim), path(fam) from test1_results

    output:
    tuple val("${sample_name}-t2"), path("${sample_name}-t2.{bed,bim,fam}") into test2_results

    """
    plink \\
        --bed "${bed}" \\
        --bim "${bim}" \\
        --fam "${fam}" \\
        --maf 0.01 \\
        --make-bed \\
        --out "${sample_name}-t2"
    """
}

Note that in the first example, bfiles could be replaced with "*" since no reference is made to the tuple of bfiles anyway. Also note that the list of files produced using the fromFilesPairs operator are returned in lexicographic order.

> **Comments:**
> **username_0**: Thanks @Steve, I modified the code but getting a new issue: 'process test1{ publishDir params.publish input: set t1, file(plk1) from data output: set t2, file "${t2}.{bed,fam.bim}" into test1_results script: """ plink --bfile $t1 --maf 0.05 --make-bed --out ${t2} """ ' the error is: no such variable: t2 I have 3 files (.bed,.bim,.fam), process test1 will generate another 3 (.bed,.bim,.fam) files which will be used in the next process. How could I declare t1,t2,t3 etc (the inputs and outputs) correctly?  
> **username_1**: No worries @zillurrahman, I have added some example code to show how you could declare your inputs and outputs. The inputs could just be a tuple of bfiles or each file could be referenced separately. I haven't used plink before and have only had a (very) quick read of the docs, so there may be some more issues. Hopefully it's enough to get you started.  
> **username_0**: Thanks a lot @Steve. It works as I expected! One thing, plink also generate a log file, I need this as one of the outputs but the log will not be used in the next process. Now I am adding more processes in the script, I will get back to you if I got stuck again.  
> **username_1**: So for Nextflow to be able to publish a file using the publishDir directive, it (the file) needs to be referenced in your process' output declaration block somehow. If it's not required by any downstream process, you can just add another output channel, for example: `path("${sample_name.log}") into test1_logs`. Please let me know if that doesn't make sense. Cheers.  
> **username_0**: Thank you @Steve, It seems I can declare multiple output, which is very much useful for my pipeline. Just one thing, if I  'path("${sample_name.log}") into test1_logs' it shows 'No such variable: log'.  
> **username_1**: Erp there's a typo in there.. you'll need: `path("${sample_name}.log") into test1_logs` if your log's filename fits that format. Whether it does or not, you'll need to check. HTH.  
> **username_0**: Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/121077/discussion-between-zillur-rahman-and-steve).  
> **username_0**: Thanks @Steve, I also tried it. If I use path("${sample_name}.log") , it shows error execution prosess; caused by missing output files. If I use path("${sample_name}".log) , it shows no such variable: log  
> **username_1**: What's the name of your log file? I haven't run plink before, so I just used `"${sample_name}.log"` as an example. If the name of the log file is 'plink.log' then you'd use: `path("plink.log") into test1_logs` in your output declaration.  
> **username_0**: Thanks @Steve, The final output.log is the log file. Sorry I failed to clarify. However, path("${sample_name}-t1.log") into test1_logs works as I expected! Thank a lot again.  

---

