RiserBob logoRiserBobv1.0.0
HomeDocsCLIRelease notes

Getting started

  • Introduction
  • Installation
  • Quick start
  • Project structure

Core concepts

  • Routing
  • Request
  • Responses
  • Error handling

Middleware

  • Middleware
  • Authentication
  • Logger and CORS

Data

  • Validation

Structure and tooling

  • Modules
  • CLI

Examples

  • Build a project
  • Mongoose
  • Drizzle ORM
  • Sequelize
  • JWT and cookies
  • File uploads

Packages

  • Cookies

Resources

  • Troubleshooting
  • Release notes
  • License
  • Security
  • Contributing
Resources

Troubleshooting

The errors people meet most often with RiserBob, what causes them and how to fix them.

Find your symptom, read the cause, apply the fix. Most problems come from a handful of habits, and every one of them is visible in the server log.

A request returns 500

Handler did not send a response

The handler finished without returning a Response. The most common cause is a generated controller whose body is still a TODO, or a missing return.

TypeScript
// Wrong: the Response is created and thrown awayreadonly findAll: SpongHandler = async (spongReq, spongRes) => {  spongRes.SpongOK({ success: true });}; // Rightreadonly findAll: SpongHandler = async (spongReq, spongRes) => {  return spongRes.SpongOK({ success: true });};

Status 204 cannot have a response body

json() refuses a body for 204, 205 and 304. Use SpongNoContent() for an empty success, or answer 200 with a message.

A database error with an unreadable message

Any error that is not an HttpError becomes Internal Server Error for the client on purpose. Read the real error in the server log. When the cause is a bad id, validate it first. See Error handling.

A request returns 4xx

SymptomCauseFix
401 on every protected route of a new moduleThe generated verifyToken returns null.Implement verifyToken, or remove the auth middleware from a public route.
401 although you are logged inThe middleware reads a different source than you send. The mode may be 'cookie' while the client sends a header, or the cookie name differs.Match mode and cookieName to what the client sends. See Authentication.
401 with a header in 'both' modeA request with an Authorization header is judged by the header alone. A value that is not Bearer <token> is rejected and the cookie is not tried.Send a valid Bearer header, or do not send the header.
405 Method Not AllowedThe path exists, but not for that method. The Allow header lists the valid ones.Use a listed method, or register the method you need.
404 Not Found for a route that existsA different path, a different method, or the route was never registered. The server log prints the method and the path it received.Compare the log with your registration. Make sure the module is registered in src/index.ts.
415 Unsupported Media Typejson() needs Content-Type: application/json.Send the header, for example curl -H "Content-Type: application/json".
400 Invalid JSON bodyThe body is not valid JSON. A trailing comma or single quotes are the usual cause.Validate the JSON before sending it.
413 Content Too LargeThe request is bigger than 10 MiB.Send less data, or upload large files straight to a storage service.

The server fails to start

MessageCauseFix
must start with "/"A route path has no leading slash.Write /users, not users.
Route "GET /x" already lives in Bikini BottomThe same method and path were registered twice.Remove the duplicate. Two modules may be declaring the same path.
CORS cannot use "*" with credentials enabledcorsMiddleware was created with origin: '*' and credentials: true.List the allowed origins explicitly.
Unknown validation rule or required and nullable cannot be combinedA rule file has a typo, or a field uses both rules.Fix the schema. The error is thrown the first time that schema is used.
DATABASE_URL is missingThe .env file is missing, or it is not in the project root.Create .env next to package.json and restart the server.

Middleware does not run

Global middleware is ignored

Global middleware is attached when a route is registered, so spongUse only affects the routes registered after it.

TypeScript
// Wrong: the route is registered firstbob.spongGet("/", handler);bob.spongUse(loggerMiddleware); // Rightbob.spongUse(loggerMiddleware);bob.spongGet("/", handler);

next() called multiple times

A middleware called spongNext() twice. Call it once and return its result, for example return spongNext().

The admin middleware always answers 401

It reads spongReq.user, which AuthMiddleware sets. Pass the auth middleware first and the admin middleware second.

Cookies and CORS

SymptomCauseFix
The browser never stores the cookieThe cookie was set, but applyTo was not called on the response you returned.Return cookies.applyTo(response).
The cookie is missing on http://localhostSecure cookies are the default, and some browsers refuse them over plain HTTP.Create the manager with defaults: { secure: false } in development.
Logout does not log you outThe deleted cookie was not applied, or path, domain or sameSite differ from the original.Call applyTo and pass the same attributes you used in set.
The browser reports a CORS errorThe request origin is not in origin, or the front end does not send credentials.Add the exact origin, and use fetch(url, { credentials: 'include' }).
The cookie is sent, but the user is not foundAuthMiddleware reads the cookie with a plain get.Do not use setSigned for the token cookie, or verify the signature in your verifier.

TypeScript

MessageCauseFix
Type 'string | undefined' is not assignable to type 'string' on params.idnoUncheckedIndexedAccess is on. A route parameter might be missing.Check it first: if (!id) return spongRes.SpongBadRequest().
Not all code paths return a value in a handlerA branch ends without a return.Return a Response on every path.
'X' is a type and must be imported using a type-only importverbatimModuleSyntax is on.Write import type { SpongHandler } from "riser-bob".
A property is missing on spongReq.userThe user has an id and whatever your verifier returned. Other fields have the type unknown.Return the fields you need from the verifier, and narrow them before use.

Still stuck

Read the server log first: RiserBob prints what it received and why it answered as it did. If it still looks like a framework bug, open an Issue with the steps to reproduce. See Contributing.

PreviousCookiesNextRelease notes

On this page

  • A request returns 500
  • Handler did not send a response
  • Status 204 cannot have a response body
  • A database error with an unreadable message
  • A request returns 4xx
  • The server fails to start
  • Middleware does not run
  • Global middleware is ignored
  • next() called multiple times
  • The admin middleware always answers 401
  • Cookies and CORS
  • TypeScript
  • Still stuck