# workerd error: subrequest to self rejected

## TL;DR

The worker tried to fetch its own public URL, which workerd rejects to prevent loops. Call the logic directly (shared function) or fetch the origin behind the worker, not the worker itself. Self-fetch is a design smell.

```text
workerd error: subrequest to self rejected
```

## Steps

1. Find the self-fetch: which code path requests the worker's own URL.
   Expected: The call site is located.

2. Refactor to call the shared logic directly instead of over HTTP.
   Expected: No network hop is needed.

3. If the HTTP boundary is required, fetch the origin service behind the worker.
   Expected: The request goes somewhere real.

4. For testing, use the worker's internal dispatch, not its public URL.
   Expected: Tests do not self-fetch.

5. Remove the self-fetch pattern from the codebase.
   Expected: The design is clean.

## When to use

- workerd rejects a subrequest to self
- a worker calls its own URL
- refactoring monolith handlers

## When not to use

- the fetch targets a different service (check the URL)
- the rejection is on another rule (read the error)
- using service bindings (the right way to call sibling workers)

## Tool compatibility

- workerd
- subrequests

## Variant phrasings

- "workerd subrequest to self"
- "self fetch rejected worker"
- "worker fetch own url rejected"

## Why it happens

A worker fetching its own URL would recurse: the request re-enters the worker, which fetches itself again. Workerd rejects it outright rather than let the loop form. The fix is architectural: shared code should be a function call, and sibling workers should use service bindings.

## Edge cases

- service bindings are the sanctioned worker-to-worker path
- the rejection is per-request; it does not poison the worker
- staging URLs count as self too; check the host matching

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_QrLzj1Dw5LgVYH8XJTGXng
