|
| 1 | +# ERRORS LEARNED |
| 2 | + |
| 3 | +<!-- Format: EL-NNN, Date, Context, Error/Symptom, Root Cause, Fix, Prevention Rule, Tag, Reusability --> |
| 4 | +<!-- Newest entries at top --> |
| 5 | + |
| 6 | +## EL-009 |
| 7 | +**Date:** 2026-04-09 |
| 8 | +**Context:** Dockerfile viroprofiler-geneannot — COPY + dynamic path |
| 9 | +**Error/Symptom:** `COPY ./path/file /opt/conda/lib/python3.10/site-packages/pkg/` — Dockerfile `COPY` instruction does not support shell variable expansion, so hardcoded Python version paths will break when conda resolves a different version. |
| 10 | +**Root Cause:** Docker `COPY` destination is evaluated at build time without shell; cannot use `$(...)` expansion. |
| 11 | +**Fix:** `COPY ./path/file /tmp/file` then `RUN SITE_PKGS=$(python3 -c "import site; print(site.getsitepackages()[0])") && cp /tmp/file $SITE_PKGS/pkg/` |
| 12 | +**Prevention Rule:** Never use Python version paths in Dockerfile `COPY` destinations; always COPY to `/tmp/` first, then use a `RUN` layer with `site.getsitepackages()` to move to the correct location. |
| 13 | +**Tag:** docker, python, path, COPY |
| 14 | +**Reusability:** high |
| 15 | + |
| 16 | +## EL-008 |
| 17 | +**Date:** 2026-04-09 |
| 18 | +**Context:** bin/parse_mmseqsTaxa.py — column selection after commented-out initialization |
| 19 | +**Error/Symptom:** `df_formatted[['contig_id', ..., 'Strain']]` raises `KeyError: 'Strain'` at runtime when `dbsource == "ICTV"`. No error at import time. |
| 20 | +**Root Cause:** The code block that populates the `'Strain'` column (lines 24-30) was commented out, but the column reference in the selector (line 79) was not updated to match. |
| 21 | +**Fix:** Remove `'Strain'` from the column selector in line 79 (or restore the extraction logic if Strain is needed). |
| 22 | +**Prevention Rule:** When commenting out initialization logic that creates a new column/variable, grep for all downstream references and update or remove them atomically. |
| 23 | +**Tag:** python, pandas, commented-code |
| 24 | +**Reusability:** high |
| 25 | + |
| 26 | +## EL-007 |
| 27 | +**Date:** 2026-04-09 |
| 28 | +**Context:** VIRSORTER2 process stub block |
| 29 | +**Error/Symptom:** VIRSORTER2 script uses `ln -s out_vs2/for-dramv/file .` to create top-level symlinks. In stub mode, the source directory doesn't exist, so `ln -s` would fail. |
| 30 | +**Root Cause:** Symlinks require source files to exist; in stub mode there are no real tool outputs |
| 31 | +**Fix:** Create actual files directly at the expected paths (`cp` instead of `ln -s`) in the stub block |
| 32 | +**Prevention Rule:** In Nextflow stub blocks, replace `ln -s` with direct file creation (`cp` or `printf`) — symlinks require source files that don't exist in stub context |
| 33 | +**Tag:** nextflow, stub, symlink |
| 34 | +**Reusability:** high |
| 35 | + |
| 36 | +## EL-006 |
| 37 | +**Date:** 2026-04-09 |
| 38 | +**Context:** VIBRANT process stub + VIRCONTIGS_PRE dependency |
| 39 | +**Error/Symptom:** VIBRANT emits `path("VIBRANT_*")` (entire directory), but VIRCONTIGS_PRE directly accesses `${vibrant_dir}/VIBRANT_phages_contigs/contigs.phages_combined.fna` at line 144. A stub that only `touch`es top-level files would make this downstream access fail. |
| 40 | +**Root Cause:** Directory emit hides the fact that downstream processes access specific deep paths inside the emitted directory |
| 41 | +**Fix:** Stub block must replicate the complete directory structure with all files that downstream processes actually access |
| 42 | +**Prevention Rule:** When a process emits a directory, grep all downstream process scripts for paths into that directory — stub must create every accessed path |
| 43 | +**Tag:** nextflow, stub, directory-emit, vibrant |
| 44 | +**Reusability:** high |
| 45 | + |
| 46 | +## EL-005 |
| 47 | +**Date:** 2026-04-09 |
| 48 | +**Context:** Dockerfile for viroprofiler-binning |
| 49 | +**Error/Symptom:** `python3.1` in site-packages path — clearly a typo (should be 3.10 or 3.11) |
| 50 | +**Root Cause:** Hardcoded Python version path instead of dynamic detection |
| 51 | +**Fix:** Use `$(python3 -c "import site; print(site.getsitepackages()[0])")` for dynamic path |
| 52 | +**Prevention Rule:** Never hardcode Python version paths in Dockerfiles; always use dynamic detection via `site.getsitepackages()` |
| 53 | +**Tag:** docker, python, path |
| 54 | +**Reusability:** high |
| 55 | + |
| 56 | +## EL-004 |
| 57 | +**Date:** 2026-04-09 |
| 58 | +**Context:** bin/normalize_abundance.py |
| 59 | +**Error/Symptom:** `df.applymap()` will fail with pandas >= 2.1.0 |
| 60 | +**Root Cause:** API deprecated in pandas 2.0, removed in 2.1 |
| 61 | +**Fix:** Replace `applymap` with `map` (DataFrame.map was added as replacement) |
| 62 | +**Prevention Rule:** Check pandas deprecation warnings when using DataFrame methods; `applymap` -> `map`, `append` -> `concat` |
| 63 | +**Tag:** python, pandas, deprecation |
| 64 | +**Reusability:** high |
| 65 | + |
| 66 | +## EL-003 |
| 67 | +**Date:** 2026-04-09 |
| 68 | +**Context:** modules/local/abundance.nf MAPPING2CONTIGS2 |
| 69 | +**Error/Symptom:** Pipeline would crash on single-end data — `illumina[1]` index out of bounds |
| 70 | +**Root Cause:** Defined SE/PE variable but hardcoded PE syntax in the actual command |
| 71 | +**Fix:** Use the prepared `$illumina_reads` variable instead of hardcoded `-1 ${illumina[0]} -2 ${illumina[1]}` |
| 72 | +**Prevention Rule:** When adding SE support to Nextflow processes, always verify the script block uses the conditional variable, not just the def line |
| 73 | +**Tag:** nextflow, single-end, bowtie2 |
| 74 | +**Reusability:** high |
| 75 | + |
| 76 | +## EL-002 |
| 77 | +**Date:** 2026-04-09 |
| 78 | +**Context:** modules/local/binning.nf VAMB process |
| 79 | +**Error/Symptom:** `VAMB.out.vamb_clusters_ch` would fail — no named emit exists |
| 80 | +**Root Cause:** VAMB outputs defined without `emit:` names, but subworkflow references named emit |
| 81 | +**Fix:** Add `emit: vamb_clusters_ch` to the output declaration |
| 82 | +**Prevention Rule:** When referencing process outputs by name (`.out.name`), always verify the process has a matching `emit:` declaration |
| 83 | +**Tag:** nextflow, emit, channel |
| 84 | +**Reusability:** high |
| 85 | + |
| 86 | +## EL-001 |
| 87 | +**Date:** 2026-04-09 |
| 88 | +**Context:** workflows/viroprofiler.nf BRACKEN call |
| 89 | +**Error/Symptom:** Groovy syntax error — unquoted string interpolation in function argument |
| 90 | +**Root Cause:** `${params.db}/kraken2` passed without quotes — Groovy interprets this as code, not a string |
| 91 | +**Fix:** Wrap in quotes: `"${params.db}/kraken2"` |
| 92 | +**Prevention Rule:** In Nextflow/Groovy, always quote string interpolations when passing paths as process arguments |
| 93 | +**Tag:** nextflow, groovy, syntax |
| 94 | +**Reusability:** high |
0 commit comments