Skip to content

OUT-3680: read webhook body before sleep to avoid ECONNRESET#101

Merged
SandipBajracharya merged 2 commits intomainfrom
OUT-3680
May 4, 2026
Merged

OUT-3680: read webhook body before sleep to avoid ECONNRESET#101
SandipBajracharya merged 2 commits intomainfrom
OUT-3680

Conversation

@SandipBajracharya
Copy link
Copy Markdown
Collaborator

@SandipBajracharya SandipBajracharya commented May 4, 2026

Summary

  • Assembly and Dropbox webhook handlers were sleeping 800ms, authenticating, and querying the DB before reading req.json(). Over a tunnel (ngrok / upstream LB) the request body stream was being aborted by the time we tried to parse it, surfacing as Error: aborted { code: 'ECONNRESET' } right after the Authorizing with key: log from the Copilot SDK.
  • Fix: consume the body first, then sleep and process. parseWebhook now takes the parsed body instead of the NextRequest.
  • Also tightened Assembly webhook validation: switched to webhookEvent.data.object (the authoritative field from Copilot) and dropped the unused top-level object from AssemblyWebhookSchema.

Test plan

  • Trigger an Assembly file.created webhook and confirm no ECONNRESET; sync still flows through to Dropbox
  • Trigger an Assembly file.updated and file.deleted webhook
  • Trigger a Dropbox webhook and confirm signature validation still passes (body is now read before sleep)
  • Verify link-type Assembly objects are still skipped via data.object check

🤖 Generated with Claude Code

The Assembly and Dropbox webhook handlers slept 800ms, authenticated, and
queried the DB before consuming the request body. With the upstream tunnel
holding the socket open, the body stream was getting aborted (ECONNRESET)
by the time `req.json()` ran. Read the body first, then sleep and process.

Also tighten Assembly webhook validation: switch to `webhookEvent.data.object`
(authoritative source from Copilot) and drop the unused top-level `object`
field on `AssemblyWebhookSchema`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 4, 2026

@vercel
Copy link
Copy Markdown

vercel Bot commented May 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dropbox-integration Ready Ready Preview, Comment May 4, 2026 7:37am

Request Review

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 4, 2026

Greptile Summary

This PR fixes ECONNRESET errors in both Assembly and Dropbox webhook handlers by consuming the request body (req.json() / req.text()) before the 800 ms sleep and downstream async work, preventing upstream proxies from tearing down the stream. It also cleans up the Assembly webhook validation: parseWebhook is now a synchronous method taking an already-parsed body, and validateHandleableEvent correctly ANDs the event-type check with a data.object type check (replacing a || that inadvertently allowed 'link'-typed objects through when the event type matched).

Confidence Score: 4/5

Safe to merge; only a P2 style finding present.

The body-before-sleep fix is sound for both handlers, the parseWebhook refactor is clean, and the || → && logic change correctly tightens validation. One P2 note about a redundant middle operand in the && chain that widens the TypeScript inferred type, but no correctness issues.

src/features/webhook/assembly/lib/webhook.service.ts — redundant truthiness check in validateHandleableEvent widens inferred type.

Important Files Changed

Filename Overview
src/features/webhook/assembly/api/webhook.controller.ts Reads req.json() before sleep/auth to prevent ECONNRESET; passes parsed body to parseWebhook — correct fix.
src/features/webhook/assembly/lib/webhook.service.ts parseWebhook made sync (takes unknown body); validateHandleableEvent logic changed from
src/features/webhook/assembly/utils/types.ts Removed unused top-level object field from AssemblyWebhookSchema; clean change.
src/features/webhook/dropbox/api/webhook.controller.ts req.text() moved before sleep so body is consumed before the 800ms delay; HMAC validation is unaffected.

Sequence Diagram

sequenceDiagram
    participant C as Client
    participant AW as Assembly Webhook
    participant DW as Dropbox Webhook
    participant WS as WebhookService

    Note over C,WS: Assembly flow after fix
    C->>AW: POST request
    AW->>AW: consume body first
    AW->>AW: sleep 800ms
    AW->>AW: authenticate user
    AW->>WS: parseWebhook(parsedBody)
    WS-->>AW: webhookEvent
    AW->>WS: validateHandleableEvent
    WS-->>AW: eventType or null
    AW-->>C: 200 OK

    Note over C,DW: Dropbox flow after fix
    C->>DW: POST request
    DW->>DW: check signature header
    DW->>DW: consume body first
    DW->>DW: sleep 800ms
    DW->>DW: verify HMAC
    DW-->>C: 200 OK
Loading

Reviews (1): Last reviewed commit: "fix(OUT-3680): read webhook body before ..." | Re-trigger Greptile

Comment thread src/features/webhook/assembly/lib/webhook.service.ts Outdated
@SandipBajracharya SandipBajracharya changed the title fix(OUT-3680): read webhook body before sleep to avoid ECONNRESET OUT-3680: read webhook body before sleep to avoid ECONNRESET May 4, 2026
Copy link
Copy Markdown
Collaborator

@priosshrsth priosshrsth left a comment

Choose a reason for hiding this comment

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

lgtm

@SandipBajracharya SandipBajracharya merged commit 7188dc4 into main May 4, 2026
4 checks passed
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.

2 participants