Troubleshooting
Common issues when developing with Forte.
Build / Codegen
route_generated.rs is wrong after adding a handler
Codegen runs during cargo build (via build.rs). If the generated file looks stale:
# From rs/ inside a Forte project
cargo build
Or regenerate everything including TypeScript types:
forte build
Handler not being discovered
Codegen uses static analysis (not Rust compilation) to discover handlers. Make sure the file matches the exact naming conventions:
| Type | Required names | Location |
|---|---|---|
| Page | pub async fn handler returning Result<Props> | src/pages/ (recursive) |
| API | pub async fn handler returning Result<Props> | src/apis/ (recursive) |
| Action | struct Input, Output type, pub async fn handler | src/actions/ (flat or <name>/mod.rs) |
| Hook | struct Input, Output type, pub async fn handler | src/hooks/ (flat .rs only) |
| Queue task | struct Input or type Input, pub async fn handle | src/queue_task/ (flat .rs only) |
| Admin task | struct Input or type Input, pub async fn handle | src/admin/ (flat .rs only) |
| Static file | any file | public/ (recursive) |
For pages/APIs the return type string must contain both "Result" and "Props". Naming the type Props is the simplest way to satisfy this.
For actions and hooks, Input must be a struct (not a type alias). For queue/admin tasks pub type Input = () is also accepted.
Nested paths under src/actions/ (e.g. src/actions/user/login.rs) are not discovered — only flat files and <name>/mod.rs.
lib.rs is missing the forte-managed marker block
The build panics if src/lib.rs does not contain the managed block markers. Add them:
// === FORTE-MANAGED START ===
// Auto-managed by `forte build`. Do not edit between the START/END markers.
mod route_generated;
// === FORTE-MANAGED END ===
Then re-run forte build.
forte dev
forte dev fails to start sqld
Symptom: sqld did not become ready within 5 seconds
- Another process may be using the sqld port. Try stopping any other local DB services.
- The sqld binary may be corrupted. Clear the cache and retry:
rm -rf ~/.forte/bin/sqld-* forte dev
Environment variable changes don't take effect
forte dev hot-reloads env.yaml and env.local.yaml on file change — updated values for existing variables take effect on the next request without a Rust rebuild.
Adding a new variable still requires a cargo build, because generate_env() emits its accessor function at build time.
env.local.yaml is local-only: it is gitignored and never bundled into a deploy. env.yaml is the one that ships.
forte-rs-to-ts
TypeScript types are not generated
forte-rs-to-ts runs during forte build and forte dev. If the generated .props.ts or .generated/*.ts files are missing:
- Check that
forte buildorforte devcompleted without errors. - Verify the Rust handler compiles successfully (
cargo buildinrs/). - Check that the platform is supported:
aarch64-apple-darwin,x86_64-unknown-linux-gnu,aarch64-unknown-linux-gnu. Windows is not supported.
To force a fresh download of the tool:
rm -rf ~/.forte/bin/forte-rs-to-ts-*
forte build
Testing
cargo test builds but doesn't run (WASM crates)
A Forte project's rs/ crate targets wasm32-wasip2. Without the forte-test-runner configured, cargo test compiles the test binary but cannot execute it.
Add the runner to rs/.cargo/config.toml:
[build]
target = "wasm32-wasip2"
[target.wasm32-wasip2]
runner = "forte-test-runner"
Install the runner from the monorepo:
cargo install --path <monorepo>/forte/test-runner
forte init does not add the runner configuration automatically.
doc-db or object-storage tests fail
These crates compile to wasm32-wasip2 for tests and require:
forte-test-runnerin PATH.- A running libSQL server for
doc-dbtests:docker compose up -d libsql-test
See development.md for full prerequisites.
forte dev local data
Reset local database
The local libSQL database is stored in .forte/data/ inside your project directory. To wipe it and start fresh:
rm -rf .forte/data/
forte dev
forte dev recreates the directory on next start.
Reset local object storage
Local object storage files are stored in .forte/data/objects/. To clear all objects without dropping the database:
rm -rf .forte/data/objects/
Deployment
forte deploy fails on first run
forte deploy needs you to be authenticated:
forte login
forte deploy
Copy the URL printed by forte login into any browser, approve access, and paste the one-time code into the CLI prompt.
Environment variables not available in production
Secrets and env vars set via forte env set are stored in env.yaml and bundled during forte deploy. Plain entries are also read by forte dev; encrypted ones are not, since decrypting needs the vault — override those in env.local.yaml for local runs.
Cron jobs not firing
- Verify
cron.yamlexists in the project root. - Each
functionmust match ars/src/queue_task/<name>.rsfile. - That task's
Inputmust be empty:pub struct Input;,pub struct Input {},pub struct Input(), orpub type Input = (). - Cron jobs are registered during
forte deploy. Runforte deployagain after adding or changingcron.yaml.
Telemetry
OTLP export warnings in forte dev
Symptom: Warnings like "otlp metrics export failed" or "OTLP trace export returned ..." appear in the forte dev terminal.
forte dev does not intercept the fn0-otel.fn0.dev placeholder hostname, so OTLP span and metric export attempts made by the WASM component at the end of each request fail with a connection error. These warnings are harmless and do not affect request handling.
Tracing macro output (tracing::info!, tracing::error!, etc.) still appears in the dev server terminal as usual — only the OTLP export path is inactive locally. OTLP export is active in production (fn0 Cloud).
WebSocket Singleton
Singleton not connecting after deploy
WebSocket singletons are registered during forte deploy from .forte/ws_singletons.json, which is written by forte build. If the singleton was added or renamed:
- Run
forte build(orforte dev) to regenerate.forte/ws_singletons.json. - Run
forte deployto register the updated manifest with the control plane.
The singleton module must define pub async fn connect returning Result<SingletonConnectionOptions> and pub async fn on_message. Dynamic path segments ([param]) in the module path are rejected at build time.
Singleton reconnect after a deploy
A deploy closes project connections when the worker adopts the new code version. Your on_disconnect
callback receives DisconnectCause::Deployment when the old connection observes that close. The
new connection is opened automatically from the active deployment declaration. A rolling deploy
does not guarantee that the old close handshake completes before the replacement dial starts.
Named singleton send returns ConnectionNotFound
crate::ws_singleton::<module>::send looks up the singleton's current connection once. It fails
with ConnectionNotFound when the singleton is still connecting, when its lease has expired, when
the active deployment differs from the connection's deployment, or when the owner was replaced
between the lookup and the write. The message is not retried on the replacement connection;
retry from application code if the protocol allows it. Named send is not available in
forte dev, which does not open singletons.
Outbound connection refused with DestinationForbidden
The URL resolved only to addresses that are not on the public internet, such as localhost,
private networks, or 169.254.169.254. The same policy refuses Rust HTTP requests with
destination-IP-prohibited and JavaScript fetch with status 403. See
Outbound destinations.
429 Monthly egress quota exhausted
The project used its monthly compute egress. WebSocket sends fail with EgressQuotaExceeded and
the connection closes with DisconnectCause::EgressQuotaExceeded (close code 1008). See
Limits & Quotas.
Singleton status is unavailable
Forte intentionally does not expose public singleton status, pause, or resume operations. The
websocket_singleton_status action is an internal worker heartbeat and disconnect endpoint, not a
read action. Use worker and control logs when diagnosing connection ownership or reconnects. To
stop or restore a singleton, change its deployed module declaration and deploy that change.