Skip to content

Troubleshooting and FAQ

The page for when something is not working, or you have a question the guides did not answer. Every heading is one problem or question; scan the list on the right.

Every resource fails, and alchemy dev keeps running anyway — so the terminal looks busy rather than broken:

Terminal window
[Store] fail (local)
alchemy dev: apply failed; keeping dev alive so healthy resources keep serving.
AuthError: No credentials configured for 'Cloudflare' in profile 'default',
and this process is non-interactive so it can't be configured interactively.

Two stack traces follow. Nothing will come up; stop it with Ctrl-C.

The local emulator wants placeholder Cloudflare credentials even though it never talks to Cloudflare. Three do it:

.env
CI=1
CLOUDFLARE_ACCOUNT_ID=0123456789abcdef0123456789abcdef
CLOUDFLARE_API_TOKEN=x

alchemy dev reads .env on its own. CI=1 is what makes it read the environment at all, instead of a login profile; alchemy login is the alternative if you would rather store real credentials once. These are placeholders: the account id must be 32 hex characters — local fails with 'local' is not a valid Cloudflare account ID — and the token can be anything. ALCHEMY_STATE=local is unnecessary when your stack calls Alchemy.localState(). In a clone of this repository, bun run dev:reef and bun run dev:todos set everything.

The server says ready but nothing ever loads

Section titled “The server says ready but nothing ever loads”

Requests hang rather than fail. Check main in resources.ts:

resources.ts
main: "ramose/worker", // resolves to nothing; never boots
main: import.meta.resolve("ramose/worker"), // a real path — this one works

main is resolved as a file path, so a bare module specifier quietly finds no entry and no Worker is bundled. The tell is the startup output: a Worker that booted prints Started in NNNms after ready at …. Without it, everything downstream — including the step that installs your schema — waits on a server that never answers.

alchemy dev watches the stack files, so saving schema.ts re-applies it on its own: Plan: 1 to update, then [todos] updated. If you restarted instead, you will see [todos] noop — the change already landed.

The terminal says the Worker’s code had hung

Section titled “The terminal says the Worker’s code had hung”

The Workers runtime canceled this request because it detected that your Worker's code had hung appears when a tab closes. It is the local emulator reaping a live-query socket, not a crash. The server keeps serving.

It should: two windows on the same database update each other within about a second, locally and deployed. Check that both tabs use the same origin, the same database name, and the same server (:1337 locally, or wherever it actually came up).

Ctrl-C stops alchemy dev. Your data lives in .alchemy/ beside your stack file and survives a restart; delete that folder — or run from another directory by accident — to start from an empty database. alchemy destroy tears the stack down and deletes your data. Nothing is stored anywhere else.

Yes:

Terminal window
bun add ramose react react-dom

npm install and pnpm add work the same. One package: effect, alchemy and the two @effect/platform-* packages come with it, at versions that resolve, so there is no @rc to remember. React is an optional peer — a server-only app installs ramose alone.

Getting started builds a todo app from an empty folder.

ramose ships compiled ESM with type declarations, so an ordinary install needs no tsconfig.json setting. If your editor cannot find it, check the install landed (npm ls ramose) before reaching for moduleResolution.

Inside a clone of this repository it resolves from source instead, through the ramose paths in the root tsconfig.json — run bun install at the root.

A sign-in token names one database in its ramose.db claim, and it must equal the name you passed to ramose.db(name, …). Mint one token per database — Reef asks for authClient.ramose.token({ db: slug }) when it opens a workspace. See Sign in and roles.

My token stopped working after fifteen minutes

Section titled “My token stopped working after fifteen minutes”

Tokens live at most RAMOSE_JWT_MAX_TTL seconds (900 by default). Use Ramose.token.jwt(mint), which re-mints near expiry, instead of Ramose.token.static(value). Tokens refresh themselves.

The query needed more memory on the server than the per-query limit allows. Narrow it — a tighter where, a limit, fewer fields — and retry. The limit is a setting: Query budget.

Until a policy is set, the server answers every origin. Once a policy is set, list your app’s origins in RAMOSE_ALLOWED_ORIGINS (Reef sets it in src/infra/resources.ts). The setting is ignored without a policy — Configuration.

Usually nothing to fix. Both fall back to the next free port and print where they landed:

Terminal window
WARN: Port 1337 is in use by another process; serving on 1339 instead.
Port 5173 is in use, trying another one...
[Ui] ready at http://localhost:5174/

Read the URLs off the terminal — the next free port may not be the next number. Your app is handed the server’s real URL through VITE_RAMOSE_URL, so the two never disagree.

Reef is the exception: it pins its ports, so a collision there is real. lsof -i :1337 shows who holds it — stop that process only if it is yours.

There is none. Until a policy is set, the server serves a small demo console at /; curl http://localhost:1337/health — on whichever port the server reported — answers { "ok": true, … } at any time. Your app’s screens are the dashboard.

Section titled “Can I use SQL, count, or full-text search?”

No — none of the three exist. Count rows on the client for now. The full list is in What Ramose does not have.

Can I use it without React? Without Effect?

Section titled “Can I use it without React? Without Effect?”

Without React, yes: Effect.runPromise(db.q(query)) from any TypeScript. Live queries need a WebSocket, so they work in a browser, not through a Worker service binding. Without Effect, mostly: the React hooks run it for you; elsewhere you only need Effect.runPromise and yield* inside a write.

Yes. Ramose verifies sign-in tokens; it never issues them. Any provider that publishes signing keys works, as long as the token carries sub and ramose: { db, class }With Clerk, Auth0, or your own signer.

History is kept as version numbers, not dates: asOf takes a t. Nothing prunes history — RAMOSE_RETAIN_ROOTS bounds how much storage the index costs, not how far back asOf reads — see Retention.

No. Plain TypeScript is enough. If you want the mental model, How Ramose thinks about data is a ten-minute read that assumes nothing.

Open an issue with what you ran, what you saw, and the terminal output. The Errors page lists every error the client can raise and what the user sees.