# Fix service binding to another worker failed with 404

## TL;DR

A 404 from a service binding means the binding reached the target worker but the path does not exist there. Check that the binding's `service` name matches the deployed worker name, then confirm the target worker actually handles the path you fetch. The binding carries no routing of its own; the target worker's router decides.

## Verbatim error

```text
workerd: service binding to another worker failed with 404
```

## Steps

1. In the caller's wrangler.toml, check the `[[services]]` binding: the `service` value must match the deployed target worker's name. Expected: the name matches what `wrangler deployments list` shows for the target.
2. In the caller code, note the exact path you fetch through the binding, e.g. `env.BACKEND.fetch("YOUR_INTERNAL_HOST/api/items")`. Expected: you have the full path recorded.
3. In the target worker, confirm a route or handler exists for that path. Expected: you find the handler; the 404 almost always means it is missing.
4. Add or fix the route in the target worker and redeploy it. Expected: fetching the target's own URL for that path now returns 200.
5. Retry the call through the service binding. Expected: 200 instead of 404.

## Use this when

- Fetching through a service binding returns 404
- Worker-to-worker calls fail while the target works on its own URL
- You recently renamed the target worker or changed its routes

## Not for this skill when

- The binding is undefined or the fetch fails to connect (binding config issue)
- The target returns 500s (debug the target worker's code)
- The entrypoint name is wrong (different error about entrypoints)

## Variant phrasings

- env service binding 404
- worker service binding not found route
- fetch to bound service returns 404
- service binding path not found

## Why it happens

Service bindings route by script name and then hand the request to the target worker's own router. The binding itself is healthy in the 404 case; people miss the bug because they assume the binding carries routing, when really the target worker just has no handler for that path.

## Edge cases

- The host part of a service-binding fetch URL is ignored; only the path matters.
- Renaming a worker breaks bindings silently until both sides are redeployed.
- Multiple environments need per-environment service bindings; a binding pointing at the production name from a preview env hits the wrong worker.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_1jJl-xKBVZJx1yFghBabxQ
