nf-core / nf-core/tools

Lint error: `KeyError: 'manifest.name'` with contributor ORCiD

Open
#4,416 1 comment 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Python
Stars
322
Forks
255
Avg merge
2d 3h
Merged PRs (30d)
5

Description

Description of the bug

This is a weird one. I've had it with 4.0.2 and 4.0.3dev. I'm getting the following error after adding contributors:


(nf) Watersn@LSKI4291[nf-core-funcprofiler] (dev) nf-core pipelines lint


                                          ,--./,-.
          ___     __   __   __   ___     /,-._.--~\
    |\ | |__  __ /  ` /  \ |__) |__         }  {
    | \| |       \__, \__/ |  \ |___     \`-._,-`-,
                                          `._,._,'

    nf-core/tools version 4.0.2 - https://nf-co.re


INFO     Testing pipeline: .
Running lint checks ━━━━━━━━━━━━━━━━━━━━━━━━━╸━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4 of 28 » files_unchanged
ERROR    Pipeline repository not found in /var/folders/xf/1_b09s2n24z_5p74r6mky9fw0000gr/T/tmpl9faae0z/nf-core-funcprofiler
INFO     Saving metadata file to '/var/folders/xf/1_b09s2n24z_5p74r6mky9fw0000gr/T/tmpl9faae0z/nf-core-funcprofiler'
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /Users/Watersn/mamba/envs/nf/bin/nf-core:6 in <module>                                           │
│                                                                                                  │
│   3 from nf_core.__main__ import run_nf_core                                                     │
│   4 if __name__ == '__main__':                                                                   │
│   5 │   sys.argv[0] = sys.argv[0].removesuffix('.exe')                                           │
│ ❱ 6 │   sys.exit(run_nf_core())                                                                  │
│   7                                                                                              │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/nf_core/__main__.py:130 in run_nf_core │
│                                                                                                  │
│    127 │   │   │   log.debug(f"Could not check latest version: {e}")                             │
│    128 │   │   stderr.print("\n")                                                                │
│    129 │   # Launch the click cli                                                                │
│ ❱  130 │   nf_core_cli(auto_envvar_prefix="NFCORE")                                              │
│    131                                                                                           │
│    132                                                                                           │
│    133 @tui(command="interface", help="Launch the nf-core interface")                            │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/rich_click/rich_command.py:402 in      │
│ __call__                                                                                         │
│                                                                                                  │
│   399 │   │   # Include this here because I run into a false warning                             │
│   400 │   │   # in the PyCharm IDE otherwise; for some reason PyCharm doesn't                    │
│   401 │   │   # seem to think RichGroups are callable. (No issues with Mypy, though.)            │
│ ❱ 402 │   │   return super().__call__(*args, **kwargs)                                           │
│   403 │                                                                                          │
│   404 │   @overload                                                                              │
│   405 │   def command(self, __func: Callable[..., Any]) -> RichCommand: ...                      │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/click/core.py:1569 in __call__         │
│                                                                                                  │
│   1566 │                                                                                         │
│   1567 │   def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any:                           │
│   1568 │   │   """Alias for :meth:`main`."""                                                     │
│ ❱ 1569 │   │   return self.main(*args, **kwargs)                                                 │
│   1570                                                                                           │
│   1571                                                                                           │
│   1572 class _FakeSubclassCheck(type):                                                           │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/rich_click/rich_command.py:216 in main │
│                                                                                                  │
│   213 │   │   try:                                                                               │
│   214 │   │   │   try:                                                                           │
│   215 │   │   │   │   with self.make_context(prog_name, args, **extra) as ctx:                   │
│ ❱ 216 │   │   │   │   │   rv = self.invoke(ctx)                                                  │
│   217 │   │   │   │   │   if not standalone_mode:                                                │
│   218 │   │   │   │   │   │   return rv                                                          │
│   219 │   │   │   │   │   # it's not safe to `ctx.exit(rv)` here!                                │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/click/core.py:1970 in invoke           │
│                                                                                                  │
│   1967 │   │   │   │   super().invoke(ctx)                                                       │
│   1968 │   │   │   │   sub_ctx = cmd.make_context(cmd_name, args, parent=ctx)                    │
│   1969 │   │   │   │   with sub_ctx:                                                             │
│ ❱ 1970 │   │   │   │   │   return _process_result(sub_ctx.command.invoke(sub_ctx))               │
│   1971 │   │                                                                                     │
│   1972 │   │   # In chain mode we create the contexts step by step, but after the                │
│   1973 │   │   # base command has been invoked.  Because at that point we do not                 │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/click/core.py:1970 in invoke           │
│                                                                                                  │
│   1967 │   │   │   │   super().invoke(ctx)                                                       │
│   1968 │   │   │   │   sub_ctx = cmd.make_context(cmd_name, args, parent=ctx)                    │
│   1969 │   │   │   │   with sub_ctx:                                                             │
│ ❱ 1970 │   │   │   │   │   return _process_result(sub_ctx.command.invoke(sub_ctx))               │
│   1971 │   │                                                                                     │
│   1972 │   │   # In chain mode we create the contexts step by step, but after the                │
│   1973 │   │   # base command has been invoked.  Because at that point we do not                 │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/click/core.py:1353 in invoke           │
│                                                                                                  │
│   1350 │   │   │   echo(style(message, fg="red"), err=True)                                      │
│   1351 │   │                                                                                     │
│   1352 │   │   if self.callback is not None:                                                     │
│ ❱ 1353 │   │   │   return ctx.invoke(self.callback, **ctx.params)                                │
│   1354 │                                                                                         │
│   1355 │   def shell_complete(self, ctx: Context, incomplete: str) -> list[CompletionItem]:      │
│   1356 │   │   """Return a list of completions for the incomplete value. Looks                   │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/click/core.py:907 in invoke            │
│                                                                                                  │
│    904 │   │                                                                                     │
│    905 │   │   with augment_usage_errors(self):                                                  │
│    906 │   │   │   with ctx:                                                                     │
│ ❱  907 │   │   │   │   return callback(*args, **kwargs)                                          │
│    908 │                                                                                         │
│    909 │   def forward(self, cmd: Command, /, *args: t.Any, **kwargs: t.Any) -> t.Any:           │
│    910 │   │   """Similar to :meth:`invoke` but fills in default keyword                         │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/click/decorators.py:34 in new_func     │
│                                                                                                  │
│    31 │   """                                                                                    │
│    32 │                                                                                          │
│    33 │   def new_func(*args: P.args, **kwargs: P.kwargs) -> R:                                  │
│ ❱  34 │   │   return f(get_current_context(), *args, **kwargs)                                   │
│    35 │                                                                                          │
│    36 │   return update_wrapper(new_func, f)                                                     │
│    37                                                                                            │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/nf_core/__main__.py:317 in             │
│ command_pipelines_lint                                                                           │
│                                                                                                  │
│    314 │   """                                                                                   │
│    315 │   Check pipeline code against nf-core guidelines.                                       │
│    316 │   """                                                                                   │
│ ❱  317 │   pipelines_lint(                                                                       │
│    318 │   │   ctx, directory, release, fix, key, show_passed, fail_ignored, fail_warned, markd  │
│    319 │   )                                                                                     │
│    320                                                                                           │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/nf_core/commands_pipelines.py:140 in   │
│ pipelines_lint                                                                                   │
│                                                                                                  │
│   137 │                                                                                          │
│   138 │   # Run the lint tests!                                                                  │
│   139 │   try:                                                                                   │
│ ❱ 140 │   │   lint_obj, module_lint_obj, subworkflow_lint_obj = run_linting(                     │
│   141 │   │   │   directory,                                                                     │
│   142 │   │   │   release,                                                                       │
│   143 │   │   │   fix,                                                                           │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/nf_core/pipelines/lint/__init__.py:664 │
│ in run_linting                                                                                   │
│                                                                                                  │
│   661 │                                                                                          │
│   662 │   # Run the pipeline linting tests                                                       │
│   663 │   try:                                                                                   │
│ ❱ 664 │   │   lint_obj._lint_pipeline()                                                          │
│   665 │   except AssertionError as e:                                                            │
│   666 │   │   log.critical(f"Critical error: {e}")                                               │
│   667 │   │   log.info("Stopping tests...")                                                      │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/nf_core/pipelines/lint/__init__.py:275 │
│ in _lint_pipeline                                                                                │
│                                                                                                  │
│   272 │   │   │   │   │   continue                                                               │
│   273 │   │   │   │   self.progress_bar.update(lint_progress, advance=1, test_name=test_name)    │
│   274 │   │   │   │   log.debug(f"Running lint test: {test_name}")                               │
│ ❱ 275 │   │   │   │   test_results = getattr(self, test_name)()                                  │
│   276 │   │   │   │   for test in test_results.get("passed", []):                                │
│   277 │   │   │   │   │   self.passed.append((test_name, test))                                  │
│   278 │   │   │   │   for test in test_results.get("ignored", []):                               │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/nf_core/pipelines/lint/files_unchanged │
│ .py:142 in files_unchanged                                                                       │
│                                                                                                  │
│   139 │   create_obj = nf_core.pipelines.create.create.PipelineCreate(                           │
│   140 │   │   None, None, None, no_git=True, outdir=test_pipeline_dir, template_config=templat   │
│   141 │   )                                                                                      │
│ ❱ 142 │   create_obj.init_pipeline()                                                             │
│   143 │                                                                                          │
│   144 │   # Helper functions for file paths                                                      │
│   145 │   def _pf(file_path: str | Path) -> Path:                                                │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/nf_core/pipelines/create/create.py:273 │
│ in init_pipeline                                                                                 │
│                                                                                                  │
│   270 │   │   """Creates the nf-core pipeline."""                                                │
│   271 │   │                                                                                      │
│   272 │   │   # Make the new pipeline                                                            │
│ ❱ 273 │   │   self.render_template()                                                             │
│   274 │   │                                                                                      │
│   275 │   │   # Init the git repository and make the first commit                                │
│   276 │   │   if not self.no_git:                                                                │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/nf_core/pipelines/create/create.py:387 │
│ in render_template                                                                               │
│                                                                                                  │
│   384 │   │   │   rocrate_obj.create_rocrate(json_path=self.outdir / "ro-crate-metadata.json")   │
│   385 │   │                                                                                      │
│   386 │   │   # Update the .nf-core.yml with linting configurations                              │
│ ❱ 387 │   │   self.fix_linting()                                                                 │
│   388 │   │                                                                                      │
│   389 │   │   if self.config:                                                                    │
│   390 │   │   │   config_fn, config_yml = nf_core.utils.load_tools_config(self.outdir)           │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/nf_core/pipelines/create/create.py:429 │
│ in fix_linting                                                                                   │
│                                                                                                  │
│   426 │   │   │   │   pass  # Areas without linting                                              │
│   427 │   │                                                                                      │
│   428 │   │   # Add the lint content to the preexisting nf-core config                           │
│ ❱ 429 │   │   config_fn, nf_core_yml = nf_core.utils.load_tools_config(self.outdir)              │
│   430 │   │   if config_fn is not None and nf_core_yml is not None:                              │
│   431 │   │   │   nf_core_yml.lint = NFCoreYamlLintConfig(**lint_config)                         │
│   432 │   │   │   with open(self.outdir / config_fn, "w") as fh:                                 │
│                                                                                                  │
│ /Users/Watersn/mamba/envs/nf/lib/python3.14/site-packages/nf_core/utils.py:1495 in               │
│ load_tools_config                                                                                │
│                                                                                                  │
│   1492 │   │   │   # The .nf-core.yml file did not contain template information                  │
│   1493 │   │   │   nf_core_yaml_config.template = NFCoreTemplateConfig(                          │
│   1494 │   │   │   │   org="nf-core",                                                            │
│ ❱ 1495 │   │   │   │   name=wf_config["manifest.name"].strip("'\"").split("/")[-1],              │
│   1496 │   │   │   │   description=wf_config["manifest.description"].strip("'\""),               │
│   1497 │   │   │   │   author=author_names,                                                      │
│   1498 │   │   │   │   version=wf_config["manifest.version"].strip("'\""),                       │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
KeyError: 'manifest.name'

through trial and error, I traced this to the case where rocrate is automatically detecting an (unprovided) ORCiD for one of the contributors. If I change their name so it can't fetch and ORCiD, no error is raised. This might be related to https://github.com/nf-core/tools/issues/4289, though I'm not certain.

For example, in my case, my colleague's name is unique enough that rocrate can identify an ORCiD for her. If I list her in the contributors as

        [
            name: 'Mirae Baichoo',
            affiliation: '',
            email: '',
            github: '',
            contribution: ['author', 'maintainer'], // List of contribution types ('author', 'maintainer' or 'co\
ntributor')
            orcid: ''
        ],

the above error is raised.

If I change this to

        [
            name: 'Mirae B',
            affiliation: '',
            email: '',
            github: '',
            contribution: ['author', 'maintainer'], // List of contribution types ('author', 'maintainer' or 'co\
ntributor')
            orcid: ''
        ],

This breaks rocrate's ability to find an orcid, and the lint proceeds without issues.

Command used and terminal output
$ nf-core pipelines lint
# above error

# after editing contributors in nextflow.config to prevent ORCiD retrieval
$  nf-core pipelines lint
# no error
System information

Nextflow version: 26.04.4 build 12445
Hardware: M2 Macbook pro
Executor: local
OS: MacOS
version of nf-core/tools: 4.0.2, 4.0.3dev
python: Python 3.14.3

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the failure with nf-core pipelines lint after adding a contributor with an ORCiD, then trace the command_pipelines_lint entry point in nf_core/__main__.py into the lint checks. Confirm that the KeyError: 'manifest.name' no longer occurs and that linting completes successfully.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.