Skip to content

DNS failures during inbox validation bypass circuit-breaker accounting #1055

Closed

Description

@sij411

Background

A separate outbound delivery bug was identified whilst working on #1047 . According to the review comment, the regression introduced by 68ec7b4a
affects releases from 2.0.28 through 2.3.8, so the fix should target 2.0-maintenacne.

Current behaviour

When destination validation cannot resolve an inbox hostname, validatePublicUrl() throws a UrlError. Initial inbox validation happens before the delivery transport-error handler, so this error escapes without becoming a FetchError or recording a delivery-failure metric. Outbox circuit-breaker accounting recognizes transport failures such as FetchError, so these DNS failures do not increment its failure count. DNS failures during redirect validation also remain UrlError errors instead of transport errors.

There are two DNS failure cases: the lookup throws, or it returns no usable IP addresses. The first attaches an underlying cause; the second does not. Checking error.cause != null therefore misses the second case and relies on an implementation detail.

This report is based on source inspection and the linked maintainer review; it does not claim a new runtime reproduction.

Expected behaviour and suggested fix

DNS failures should receive the same transport-error handling as other connection failures, including delivery-failure metrics and circuit-breaker accounting. Private-address policy rejections should retain their existing behavior.

  • Add a documented discriminator to UrlError to distinguish DNS failures from policy rejections. The exact property name can be settled during implementation.
  • Mark both thrown DNS lookup errors and results with no usable IP addresses as DNS failures.
  • Handle that category as a transport failure for initial inbox validation and redirect validation, preserving the underlying error for diagnostics.
  • Add deterministic regression tests for both DNS cases, policy rejections, and the affected delivery accounting, without relying on live DNS.

See also: #1047 (comment), #1047 (comment)

AI assistance

Codex (GPT-6-astra) assisted with source inspection and drafting the descriptoin.

Activity

  1. added theissue type on Sep 23, 2026
  2. dahlia commented on Sep 24, 2026

    @dahlia
    Member

    One clarification on the metrics part: the two validation sites do not behave the same way. I measured both with a test meter provider on the revision of #1047 that carried the fix:

    • A DNS failure on the inbox itself raises UrlError and records no activitypub.delivery.sent measurement at all.
    • A DNS failure on a redirect target raises UrlError and records one measurement with activitypub.delivery.success set to false.

    await validateUrl(inbox.href) sits outside the try block that records the failure, while redirect validation happens inside it. So the direct path loses both the metric and the circuit breaker, and the redirect path loses only the circuit breaker. Worth covering both in the regression tests.

  3. self-assigned this
    on Sep 24, 2026
  4. added this to the Fedify 2.4 milestone on Sep 24, 2026
  5. modified the milestone: Fedify 2.4 on Sep 28, 2026
  6. dahlia commented on Sep 28, 2026

    @dahlia
    Member

    #1060 completed the work needed on 2.0-maintenance. To fully resolve this issue, we still need a follow-up patch on 2.3-maintenance after merging the fix forward, to fix the remaining delivery metrics and verify circuit-breaker accounting for both direct and redirected inboxes.

  7. sij411 commented on Sep 28, 2026

    @sij411
    MemberAuthor

    @dahlia I'll check and open follow-up PR

  8. self-assigned this
    on Sep 28, 2026
  9. dahlia commented on Sep 28, 2026

    @dahlia
    Member

    @sij411 Thanks! #1060 hasn't been merged forward into 2.3-maintenance yet. I'll handle the forward merge and the remaining fix when preparing the next patch release, so there's no need to open a follow-up PR for now.

  10. added a commit that references this issue on Sep 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Fields

Priority

None yet

Effort

None yet

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions