Lint error: `KeyError: 'manifest.name'` with contributor ORCiD
Nobody has claimed this yet.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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