Common errors and how to fix them.
YAML parsing errors
Unknown field
unknown field `cache_ttl`, expected one of `method`, `path`, `auth`, ...
You used a field name that doesn’t exist. The error lists all valid fields. Common mistakes:
| Wrong | Correct |
|---|---|
cache_ttl: 60 | cache: { ttl: 60 } |
hooks: [validate] | controller: { before: validate } |
type: str | type: string |
method: get | method: GET |
name: users | resource: users |
fields: | schema: |
routes: | endpoints: |
Missing field
missing field `resource`
A required top-level key is missing. Every resource file must have resource, version, and schema.
Wrong type
invalid value: string "get", expected one of `GET`, `POST`, `PATCH`, `PUT`, `DELETE`
Enum values are case-sensitive. Use uppercase HTTP methods.
Invalid YAML syntax
while parsing a block mapping ... did not find expected key
This usually means incorrect indentation or a missing colon. Check:
- Consistent indentation (2 spaces, no tabs)
- Colons after every key
- Proper flow syntax:
{ type: string }not{type: string}(space after{)
Duplicate keys
duplicate key `email` in schema
Each field name must be unique within schema. Check for copy-paste errors.
Invalid field type
unknown type `varchar`, expected one of `uuid`, `string`, `integer`, `float`, `boolean`, `timestamp`, `date`, `json`, `enum`
Use the Shaperail type names, not SQL types. The codegen layer handles the mapping to SQL types.
Invalid enum values
enum field `status` must have a `values` array
Every field with type: enum must include a values array:
status: { type: enum, values: [draft, published, archived], default: draft }
Invalid ref format
invalid ref format `organizations`, expected `resource.field`
The ref field must use dot notation: ref: organizations.id.
Min greater than max
field `name`: min (200) must be less than or equal to max (100)
Check that min and max values are in the correct order.
Database connection errors
Cannot connect to Postgres
error communicating with database: Connection refused (os error 111)
- Check Postgres is running:
docker compose ps - Verify
DATABASE_URLin.envmatches the Compose port mapping - Test connectivity:
psql "$DATABASE_URL" -c "SELECT 1" - If using Docker, make sure the container is healthy:
docker compose logs postgres
Connection pool exhausted
error: timed out waiting for connection from pool
Too many concurrent requests for the pool size. Increase the pool in shaperail.config.yaml:
databases:
default:
engine: postgres
url: ${DATABASE_URL}
pool_size: 20 # default is 10
Or reduce the number of Actix workers so each worker gets enough connections.
SSL required but not configured
error: SSL connection is required
Your production Postgres requires SSL. Update the connection URL:
DATABASE_URL=postgresql://user:pass@host:5432/db?sslmode=require
Migration version mismatch
error: migration 0003 has already been applied but the file contents differ
Someone changed an already-applied migration file. Never edit migration files after they have been applied. Write a new migration to make the correction.
Relation does not exist
ERROR: relation "users" does not exist
The migration that creates the table has not been applied yet. Run:
shaperail serve # applies pending migrations on startup
Or apply manually:
DATABASE_URL=postgresql://user:pass@host:5432/db shaperail migrate
JWT and auth errors
Token expired
{ "error": "token_expired", "message": "JWT has expired" }
The JWT exp claim is in the past. Generate a new token.
Invalid signature
{ "error": "invalid_token", "message": "Invalid JWT signature" }
The token was signed with a different JWT_SECRET than the server is using. Check that JWT_SECRET in .env matches the secret used to sign the token.
Missing auth header
{ "error": "unauthorized", "message": "Missing Authorization header" }
The endpoint requires auth. Send the header:
Authorization: Bearer <token>
Insufficient permissions
{ "error": "forbidden", "message": "Role 'viewer' is not authorized for this endpoint" }
The JWT role claim does not match the auth array on the endpoint. Check the resource YAML:
endpoints:
create:
auth: [admin] # only admin can create
Owner check failed
{ "error": "forbidden", "message": "Not the resource owner" }
The endpoint uses owner in its auth array, and the requesting user’s ID does not match the resource’s owner field. This is expected behavior for ownership-based access control.
Migration errors
sqlx-cli not installed
error: shaperail migrate requires sqlx-cli
Install it:
cargo install sqlx-cli
Migration file syntax error
ERROR: syntax error at or near "ALTERR"
The generated SQL has a typo (possibly from a manual edit). Fix the SQL file in migrations/ and re-run.
Cannot add NOT NULL column without default
ERROR: column "status" of relation "users" contains null values
You added a required: true field without a default to a table that already has rows. Fix by adding a default to the schema or manually editing the migration to backfill data first. See Migrations guide.
Foreign key constraint violation during migration
ERROR: insert or update on table "posts" violates foreign key constraint
A migration added a foreign key to a column that has values not present in the referenced table. Backfill or clean the data before adding the constraint.
Job queue issues
Jobs not running
Check the following in order:
- Redis is running:
docker compose psshows Redis healthy - REDIS_URL is correct: matches the Compose port mapping in
.env - Jobs are declared: the endpoint has a
jobs:array
endpoints:
create:
jobs: [send_welcome_email]
- A worker is actually running: the scaffold does not start a job worker automatically
- A matching handler is registered: the worker’s
JobRegistryincludessend_welcome_email
Jobs stuck in pending
shaperail jobs:status
If jobs stay in pending:
- No worker may have been started at all. The default scaffold only enqueues.
- The worker may have crashed. Check application logs.
- Redis may be unreachable. Test with
redis-cli ping. - The job may be scheduled for a future time.
Jobs failing repeatedly
Jobs that fail are retried according to their retry policy. After exhausting retries, they move to the dead letter queue. Check:
shaperail jobs:status
There is no built-in jobs:retry command today. Fix the handler or dependency problem, then re-enqueue the job from the application path that created it or manually inspect the Redis dead-letter payload.
Job timeout
error: job `process_report` exceeded timeout of 30s
Increase the timeout in the resource YAML or optimize the job handler. Long running jobs should be broken into smaller steps.
Cache issues
Cache not working (stale responses)
- Verify Redis is running
- Check the endpoint declares cache:
endpoints:
list:
cache: { ttl: 60 }
- Check
REDIS_URLis set correctly in.env
Cache not invalidating
By default, cache is invalidated when the same resource is mutated (create, update, delete). If you need cross-resource invalidation, use invalidate_on:
cache: { ttl: 60, invalidate_on: [create, update, delete] }
Redis out of memory
OOM command not allowed when used memory > 'maxmemory'
Configure Redis eviction policy or increase memory:
redis-cli CONFIG SET maxmemory-policy allkeys-lru
redis-cli CONFIG SET maxmemory 256mb
Generated code issues
Files in generated/ have compile errors
Files in generated/ are overwritten on every shaperail generate and shaperail serve. Never edit them by hand. If you see compile errors:
- Run
shaperail validateto check your resource YAML - Run
shaperail generateto regenerate - If errors persist, check that your
Cargo.tomlhas the correctshaperail-runtimeversion
Controller not found
error: controller function `validate_org` not found
The resource declares a controller, but the function is not registered in the controller map or the signature does not match. Create a controller module with the expected signature and register it with ControllerMap::register(...):
use shaperail_runtime::handlers::controller::{Context, ControllerResult};
pub async fn validate_org(ctx: &mut Context) -> ControllerResult {
// your logic here
Ok(())
}
WASM plugin not loading
error: failed to load WASM plugin: plugins/hook.wasm
- Check the file exists at the specified path
- Check the
wasm-pluginsfeature is enabled (see Feature flags below) - Rebuild the WASM module if it was compiled for a different target
Feature flag mismatches
GraphQL / gRPC not working
If you added protocols: [graphql] to your config but the endpoint doesn’t appear, check your Cargo.toml:
# This won't work -- graphql feature is not enabled:
shaperail-runtime = { version = "0.7.0", default-features = false }
# This will:
shaperail-runtime = { version = "0.7.0", default-features = false, features = ["graphql"] }
WASM plugins silently ignored
If your resource declares controller: { before: "wasm:plugins/hook.wasm" } but the hook doesn’t run, enable the feature:
shaperail-runtime = { version = "0.7.0", default-features = false, features = ["wasm-plugins"] }
Without the feature, WASM prefixed controllers return an error at runtime.
Multi-database not working
If you enable the multi-db feature and route resources through named connections, remember that the generated bootstrap only wires SQL engines (postgres, mysql, sqlite) automatically:
shaperail-runtime = { version = "0.7.0", features = ["multi-db"] }
If you configure a named database with engine: mongodb, the runtime has Mongo-backed store primitives behind the feature flag, but the scaffolded app does not build the mixed SQL + Mongo store registry for you yet.
Use named SQL connections out of the box, or add manual bootstrap code for Mongo-backed stores.
Available features
| Feature | What it enables |
|---|---|
graphql | POST /graphql endpoint via async-graphql |
grpc | gRPC server via tonic on a separate port |
wasm-plugins | WASM controller hooks via wasmtime |
multi-db | Named multi-database runtime support; scaffolded apps wire SQL engines automatically |
observability-otlp | OpenTelemetry OTLP span export |
All features are enabled by default when you don’t specify default-features = false.
Performance issues
High latency on list endpoints
- Check if the endpoint has appropriate indexes:
indexes:
- { fields: [org_id, status] } # matches your common filter
- Enable caching for read-heavy endpoints:
cache: { ttl: 60 }
- Check the database with
EXPLAIN ANALYZEon the generated query
High memory usage
- Check Actix worker count – each worker uses memory. Reduce with:
# shaperail.config.yaml
workers: 4 # default is number of CPU cores
- Check for unbounded query results – always use pagination
- Monitor with
shaperail doctorfor common misconfigurations
Slow cold start
Shaperail targets cold start under 100ms. If startup is slow:
- Check migration count – many migrations take time to verify
- Check database connectivity – DNS resolution or TLS handshake may be slow
- Run
shaperail doctorto identify startup bottlenecks
Connection errors (quick reference)
| Problem | Fix |
|---|---|
| Cannot connect to Postgres | Run docker compose ps, confirm the service is healthy |
| Cannot connect to Redis | Same – check docker compose ps and .env REDIS_URL |
| Port already in use | Change the port in docker-compose.yml and update .env |
shaperail migrate fails | Install sqlx-cli: cargo install sqlx-cli |