Troubleshooting
Start by identifying the failing layer: deployment, identity, catalog, query, operation, browser synchronization, or MCP protocol. Avoid changing several layers at once.
The server is healthy but every request is denied
Section titled “The server is healthy but every request is denied”/health proves liveness, not identity configuration. Check token issuer, audience, expiry, key discovery, the principal mapping field, and the root derived for that principal. An authenticated principal with no matching root should remain denied.
Do not add an anonymous or administrator fallback. Test with one freshly issued production-shaped token and inspect safe server correlation logs.
A catalog change is rejected
Section titled “A catalog change is rejected”Read the incompatible definition list. Value representation, cardinality, uniqueness, required fields on existing records, definition identity, may require a migration.
Use an additive sequence: introduce the new shape, deploy compatible readers, backfill, switch writers, then remove the old definition. Do not force installation until you have described how existing facts and offline clients transition.
A browser query stays pending
Section titled “A browser query stays pending”pending means the local replica has no complete answer. Check that the database was actually observed, browser storage is available, authentication is current, the snapshot/resume request completed, and no terminal query error is being swallowed.
The app says stale while online
Section titled “The app says stale while online”Connectivity and catch-up are separate. The socket may be connected while a snapshot restores, a cursor resumes, or policy change forces resnapshot. Keep the complete stale result visible and inspect sync state, cursor recovery, and storage errors.
Frequent resnapshots usually point to retention, authorization churn, catalog incompatibility, or a client that fails to persist its cursor.
The same mutation appears twice
Section titled “The same mutation appears twice”Trace the invocationId. A retry of one intent must reuse the original id across timeouts, reloads, and tab leadership changes. A new user intent must receive a new id.
If the server reports invocation_conflict, the caller reused an id with a different database, operation, target, or input. Fix invocation persistence; do not hide the bug by automatically generating another id.
Optimistic state rolls back
Section titled “Optimistic state rolls back”Observe the receipt. The server may reject because authorization changed, the target disappeared, input violated a current invariant, or the operation body returned a domain rejection. Ramose removes that optimistic layer and reapplies later layers.
Show the public reason and authoritative state. Preserve user-authored input when offering a corrected new action.
A query exceeds its budget
Section titled “A query exceeds its budget”Reduce work rather than raising the global limit first:
- Start from a more selective entity or trait.
- Add an indexed equality or range filter.
- Project fewer fields.
- Bound nested collections and recursion.
- Lower the page size.
Measure server evaluation separately from database activation, local evaluation, and React rendering.
MCP returns catalog_changed
Section titled “MCP returns catalog_changed”Call describe again, replace the opaque catalog token, and rebuild exact definition references and input shapes. Do not remove ifCatalog; it prevents an agent from acting on a model it no longer understands.
MCP cannot find a tool for an operation
Section titled “MCP cannot find a tool for an operation”Operations never become separate tools. tools/list always contains describe, query, and mutate. Discover the operation reference with describe, then pass it to mutate.
Local integration tests cannot reach infrastructure
Section titled “Local integration tests cannot reach infrastructure”Run the repository’s Alchemy local integration command and confirm the shared local stack is healthy. Keep infrastructure tests on the real Worker, Durable Object, object storage, cache, WebSocket, and auth path. Use unique database names for isolation rather than replacing platform services.
Effect diagnostics disappeared
Section titled “Effect diagnostics disappeared”Run:
bunx tsc --versionThis repository expects a version suffix containing effect-tsgo. If it prints only the TypeScript version, reapply the configured patch before trusting typecheck results.
What to include in a bug report
Section titled “What to include in a bug report”Include the Ramose and TypeScript versions, deployment stage kind, failing surface, public error tag/code, safe correlation id, catalog change involved, and the smallest catalog/query/operation that reproduces the failure. Remove tokens, internal ids, and user data.