Fix chord errbacks given as a single signature by avanish-garg · Pull Request #10907 · celery/celery · GitHub
Skip to content

Fix chord errbacks given as a single signature - #10907

Open
avanish-garg wants to merge 2 commits into
celery:mainfrom
avanish-garg:fix/chord-single-link-error
Open

avanish-garg wants to merge 2 commits into
celery:mainfrom
avanish-garg:fix/chord-single-link-error

Conversation

@avanish-garg

Copy link
Copy Markdown

Note: Before submitting this pull request, please review our contributing
guidelines
.

Description

Fixes #10906

link_error may hold a single signature or a list, and every other reader wraps it with maybe_list(). Backend.chord_error_from_stack() and Backend._handle_group_chord_error() iterated the option directly. A chord body with one errback, such as tsum.s().set(link_error=eb.s()), therefore had the signature's keys iterated. The errback never ran, and one bogus task per key ('task', 'args', 'kwargs', ...) was published, showing up on the worker as "Received unregistered task of type 'task'". For a group body this happened once per body task.

Changes:

  • celery/backends/base.py: both sites now pass maybe_list(<callback>.options.get("link_error")) or [], the same idiom used in canvas.py and app/task.py.
  • t/unit/backends/test_base.py: test_chord_error_from_stack_accepts_a_single_errback and test_handle_group_chord_error_accepts_a_single_errback, each parametrized over a single signature and a list. The single-signature cases fail on main and pass with this change.

Testing:

  • pytest t/unit/backends t/unit/tasks: 1953 passed, 49 skipped, 1 xfailed.
  • flake8, isort, codespell, pyupgrade and yesqa, at the versions in .pre-commit-config.yaml, are clean on the changed files.
  • The reproduction script from the issue, run on a real worker:
# main
single link_error -> chord state FAILURE, errback called 0 time(s)
list   link_error -> chord state FAILURE, errback called 1 time(s)

# this branch
single link_error -> chord state FAILURE, errback called 1 time(s)
list   link_error -> chord state FAILURE, errback called 1 time(s)

No unregistered-task errors are logged on this branch.

link_error may hold a single signature or a list of them, and every
other reader wraps it with maybe_list(). chord_error_from_stack() and
_handle_group_chord_error() iterated it directly, so a chord body with
a single errback (e.g. body.set(link_error=eb.s())) iterated the
signature's keys: the errback never ran and one bogus task per key
('task', 'args', 'kwargs', ...) was published instead.
@auvipy
auvipy self-requested a review October 21, 2026 09:59
@codecov

codecov Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

@MehrazRumman MehrazRumman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked at d34bda9.

  • The fix is right. link_error can hold a single signature (sig.set(link_error=eb.s())), and a Signature is a dict, so iterating it yielded its keys. maybe_list(...) or [] matches how canvas.py already reads the option (lines 836 and 1201). After this change, those two sites in backends/base.py were the only remaining direct reads of options['link_error'] in celery/. The Redis backend's chord error path goes through chord_error_from_stack, so it is covered too.
  • t/unit/backends/test_base.py passes (197 passed). The two single_signature cases fail against main, and the list cases pass on both.

CI: the three failed smoke jobs (test_worker_heartbeats, test_rpc_backend, test_task_queue_max_priority) never started their tests. Each one failed while downloading the useblacksmith/setup-docker-builder action ("download has timed out ... after 3 attempts"), and that cancelled the rest of the smoke matrix. It's a runner problem, not this change; a re-run should clear it.

Looks good to me.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chord errback set as a single signature is never called; its keys are published as tasks instead

3 participants