Troubleshooting
Start from the symptom, verify the chain behavior, then change the smallest middleware or adapter boundary that explains it.
Response Is 404 Not Found
Likely causes:
| Cause | Verify | Fix |
|---|---|---|
No middleware returned a Response |
Add a temporary response at the end of the chain | Return a Response from the route or terminal middleware. |
context.passThrough() skipped the current chain |
Search for passThrough() in middleware that runs before the response |
Return immediately after passThrough() and ensure a later chain handles the request. |
| Router did not match the path | Log context.url.pathname before the router |
Register the correct path pattern or mount the router earlier. |
| Router method filter rejected the request | Check context.request.method |
Add the method, pass a method list, or use an any-method route. |
Minimal terminal middleware:
const app = chain().use(() => new Response('matched'))
If that returns matched, the adapter is working and the missing response is
inside your middleware or router branch.
Context Property Is Missing
Likely causes:
| Cause | Verify | Fix |
|---|---|---|
| Middleware returning the plugin did not run | Add a log before the plugin return | Move the plugin middleware before the consumer. |
Earlier middleware returned a Response |
Check for response returns before the plugin | Reorder middleware or move shared plugin setup earlier. |
| Chain was isolated | Search for .isolate() around the plugin chain |
Merge the chain directly when plugin output should be visible. |
| Standalone middleware lost inferred output | Hover the function return type in the editor | Annotate the return as a plugin type or define middleware inline. |
Use MiddlewareContext<typeof app> when another function should receive the
context produced by a chain.
type AppContext = MiddlewareContext<typeof app>
context.env() Returns undefined
Likely causes:
| Cause | Verify | Fix |
|---|---|---|
Host did not provide env |
Inspect the host option passed to toFetchHandler |
Add host.env or provide the value through a plugin. |
| Plugin did not provide the key | Log the object returned from middleware | Return { env: { KEY: value } } before reading the key. |
| Key name differs by case or spelling | Compare the exact string passed to context.env() |
Keep env key names as constants or a shared type. |
Host factory example:
const fetch = toFetchHandler(app, {
host: () => ({
env: name => process.env[name],
}),
})
Response Header Is Not Set
Likely causes:
| Cause | Verify | Fix |
|---|---|---|
setHeader ran after response callbacks began |
Search for setHeader inside onResponse |
Use response.headers.set() inside response callbacks. |
| Middleware setting the header never ran | Add a log next to setHeader |
Move the header middleware before branches that return a response. |
| Later middleware overwrote the header | Search for the same header name | Set the final value later in the chain. |
Use request middleware for headers that should apply to whichever response is generated.
const app = chain().use(context => {
context.setHeader('X-Trace', 'present')
})
Response Callback Does Not Run
Likely causes:
| Cause | Verify | Fix |
|---|---|---|
| Middleware that registers the callback was skipped | Put a log before onResponse |
Register callbacks earlier in the chain. |
passThrough() skipped the chain before a response existed |
Search for pass-through branches | Register callback before the pass-through or handle the request in a parent chain. |
| Isolated chain completed without a response | Check whether the isolated chain returns a response | Register callback in the parent when it should observe the parent response. |
Callbacks registered before the response is generated run even when the final
response is the default 404 Not Found.
srvx Metadata Is Missing
Likely causes:
| Cause | Verify | Fix |
|---|---|---|
| Root adapter was used with srvx | Check the import path for toFetchHandler |
Import from alien-middleware/srvx. |
| Static host override omitted a field | Inspect the host option |
Include the field or let the adapter copy it from the request. |
| Custom host factory replaced srvx values | Log the factory result | Copy request metadata into the returned host object. |
Use the srvx adapter when mounting in serve.
import { toFetchHandler } from 'alien-middleware/srvx'
Type Error When Extending RequestContext
Likely cause: the bare RequestContext defaults are stricter than you want in
an extends clause.
Use RequestContext<any> when declaring an interface that extends the context.
interface AppContext extends RequestContext<any> {
user: { id: string }
}
If the bug says "take me to your leader," start by checking which middleware actually returned the response.