All docs

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:

TypeRequired namesLocation
Pagepub async fn handler returning Result<Props>src/pages/ (recursive)
APIpub async fn handler returning Result<Props>src/apis/ (recursive)
Actionstruct Input, Output type, pub async fn handlersrc/actions/ (flat or <name>/mod.rs)
Hookstruct Input, Output type, pub async fn handlersrc/hooks/ (flat .rs only)
Queue taskstruct Input or type Input, pub async fn handlesrc/queue_task/ (flat .rs only)
Admin taskstruct Input or type Input, pub async fn handlesrc/admin/ (flat .rs only)
Static fileany filepublic/ (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:

  1. Check that forte build or forte dev completed without errors.
  2. Verify the Rust handler compiles successfully (cargo build in rs/).
  3. 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:

  1. forte-test-runner in PATH.
  2. A running libSQL server for doc-db tests:
    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.yaml exists in the project root.
  • Each function must match a rs/src/queue_task/<name>.rs file.
  • That task's Input must be empty: pub struct Input;, pub struct Input {}, pub struct Input(), or pub type Input = ().
  • Cron jobs are registered during forte deploy. Run forte deploy again after adding or changing cron.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:

  1. Run forte build (or forte dev) to regenerate .forte/ws_singletons.json.
  2. Run forte deploy to 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.