404 Not Found
What causes this
Every route in your Hono app returns 404. This usually means Hono isn’t seeing your route registrations, or the routes are registered on a different path than you’re requesting. Common causes:
- Routes are registered after the app is exported
- The
basePathis set and you’re not including it in your requests - The HTTP method doesn’t match (GET vs POST)
- In Cloudflare Workers, the
wrangler.tomlroutes don’t match - You’re exporting the wrong object
Fix 1: Register routes before exporting
import { Hono } from 'hono';
const app = new Hono();
// ✅ Register routes BEFORE the export
app.get('/', (c) => c.text('Hello'));
app.get('/api/users', (c) => c.json({ users: [] }));
app.post('/api/users', (c) => c.json({ created: true }));
export default app;
If you’re splitting routes into separate files, make sure they’re imported and mounted:
import { Hono } from 'hono';
import users from './routes/users';
const app = new Hono();
app.route('/api/users', users);
export default app;
Fix 2: Check the basePath
If you set a basePath, all routes are prefixed:
// With basePath, routes are prefixed
const app = new Hono().basePath('/api');
app.get('/users', handler);
// Actual URL: GET /api/users — NOT /users
// Without basePath
const app = new Hono();
app.get('/api/users', handler);
// Actual URL: GET /api/users
Make sure your requests include the base path.
Fix 3: Check the HTTP method
Hono is strict about methods. A POST request won’t match a GET route:
app.get('/api/data', handler); // Only matches GET
app.post('/api/data', handler); // Only matches POST
// If you want to match all methods:
app.all('/api/data', handler);
Test with the right method:
# GET request
curl http://localhost:8787/api/data
# POST request
curl -X POST http://localhost:8787/api/data
Fix 4: Cloudflare Workers — check wrangler.toml
If deploying to Cloudflare Workers, make sure your routes are configured:
# wrangler.toml
name = "my-api"
main = "src/index.ts"
# If using custom domains
[triggers]
routes = ["api.example.com/*"]
Also check that main points to the file that exports your Hono app.
Fix 5: Check you’re exporting the right thing
// ❌ Exporting the Hono constructor, not the app instance
export default Hono;
// ❌ Exporting before adding routes
const app = new Hono();
export default app;
app.get('/', handler); // Too late!
// ✅ Correct
const app = new Hono();
app.get('/', handler);
export default app;
How to prevent it
- Always register all routes before the
export defaultstatement - Use
app.all('*', (c) => c.text('Not found', 404))as a catch-all at the end to confirm Hono is running - Test routes locally with
curlor a tool like our HTTP header analyzer before deploying - If using
basePath, document it in your README so teammates know the full URL structure