Skip to content

Troubleshooting

This guide helps you diagnose and fix common issues in FraiseQL applications.

If FraiseQL isn’t working, run through this checklist first:

  1. Check the FraiseQL version

    Terminal window
    fraiseql --version
  2. Validate configuration

    Terminal window
    fraiseql validate

    Expected output when everything is correct:

    ✓ fraiseql.toml is valid
    ✓ Database connection successful
    ✓ Schema compiles without errors
    ✓ All views exist in database
  3. Test database connection

    Terminal window
    fraiseql ping

    Expected: Database: connected (PostgreSQL 16.1)

  4. Compile schema with verbose output

    Terminal window
    fraiseql compile --verbose

Error example:

Error: Syntax error in schema
→ Line 5: expected ':'

Cause: Python syntax error in schema file.

Fix: Check the indicated line for syntax issues:

# Wrong
@fraiseql.type
class User
id: str
# Correct
@fraiseql.type
class User:
id: str

Error example:

Error: Type 'Author' not found
-> Referenced in Post.author but not defined

Cause: Referenced type doesn’t exist in schema.

Fix: Define the missing type or fix the reference:

@fraiseql.type
class User: # Define the type
id: str
name: str
@fraiseql.type
class Post:
author: User # Now valid

Error example:

Error: Circular reference detected
-> User -> Post -> User

Cause: Types reference each other in a cycle.

Fix: Use forward references with strings:

@fraiseql.type
class User:
id: str
posts: list['Post'] # Forward reference
@fraiseql.type
class Post:
author: 'User' # Forward reference
# Error: Missing colon after class definition
@fraiseql.type
class User # ← SyntaxError: expected ':'
id: str
# Fix:
@fraiseql.type
class User:
id: str
# Error: Wrong annotation syntax
@fraiseql.type
class Post:
tags: List[str] # ← NameError: 'List' not defined
# Fix: use built-in list
@fraiseql.type
class Post:
tags: list[str]

Error:

Error: Failed to connect to database
-> Connection refused (os error 111)

Causes:

  1. PostgreSQL not running
  2. Wrong connection URL
  3. Network/firewall issues
  1. Check the server is running:

    Terminal window
    pg_isready -h localhost -p 5432
  2. Test the connection string directly:

    Terminal window
    psql $DATABASE_URL -c "SELECT 1"
  3. Verify the URL format:

    postgresql://user:pass@host:port/dbname

Error example:

Error: Migration failed
-> relation "tb_user" already exists

Cause: Table already exists from previous migration.

  1. Check migration status to understand what has already been applied:

    Terminal window
    fraiseql migrate status
  2. If the state is inconsistent, reset the migration history (CAUTION: drops data in development only):

    Terminal window
    fraiseql migrate reset
  3. Alternatively, remove the conflicting object manually:

    Terminal window
    psql $DATABASE_URL -c "DROP TABLE IF EXISTS tb_user CASCADE"

Error example:

Error: column "pk_user" does not exist
-> Referenced in view tv_user definition

Cause: View references non-existent column.

Fix: Check table schema matches view definition:

-- Check table columns
\d tb_user
-- Ensure column exists
ALTER TABLE tb_user ADD COLUMN pk_user INTEGER;

Error:

Error: function fn_create_user(unknown, unknown) does not exist

Cause: Function signature mismatch.

  1. Inspect the existing function signatures:

    \df fn_create_user
  2. Recreate the function with explicit parameter types:

    CREATE OR REPLACE FUNCTION fn_create_user(
    user_email TEXT,
    user_name TEXT
    ) RETURNS UUID AS $$
    ...

Error:

{
"errors": [{
"message": "Cannot query field 'username' on type 'User'. Did you mean 'name'?"
}]
}

Cause: Querying non-existent field.

Fix: Use correct field name from schema:

# Wrong
query { users { username } }
# Correct
query { users { name } }

Error:

{
"errors": [{
"message": "Variable '$id' expected type 'ID!' but got 'String'"
}]
}

Cause: Variable type doesn’t match schema.

Fix: Use correct type in query:

# Check schema for expected type
query GetUser($id: ID!) { # ID!, not String!
user(id: $id) { name }
}

Error:

{
"errors": [{
"message": "Cannot return null for non-nullable field User.email"
}]
}

Cause: Database returned NULL for required field.

Fix: Either fix data or update schema:

# Option 1: Make field nullable
email: str | None
# Option 2: Ensure data is never null
INSERT INTO tb_user (email, ...) VALUES ('required@email.com', ...)

Error:

{
"errors": [{
"message": "Email and name are required"
}]
}

Cause: SQL function validation rejected input.

Fix: Provide required fields:

mutation {
createUser(
email: "user@example.com", # Required
name: "User Name" # Required
) { id }
}

Error:

{
"errors": [{
"message": "User with email user@example.com already exists"
}]
}

Cause: Duplicate value for unique column.

Fix: Use unique value or update existing:

# Check if exists first, then update or create
mutation {
updateUser(id: "existing-id", name: "New Name") { id }
}

Error:

{
"errors": [{
"message": "Author not found"
}]
}

Cause: Referenced entity doesn’t exist.

Fix: Ensure parent entity exists:

# First create user
mutation { createUser(email: "...", name: "...") { id } }
# Then create post with valid author
mutation { createPost(authorId: "valid-user-id", ...) { id } }

Symptom: Queries take > 100ms.

Diagnosis:

-- Enable query logging
ALTER SYSTEM SET log_min_duration_statement = 100;
SELECT pg_reload_conf();
-- Check slow query log
tail -f /var/log/postgresql/postgresql.log

Common fixes:

  1. Add indexes:
CREATE INDEX idx_tv_user_email ON tv_user ((data->>'email'));
  1. Use pagination:
query { users(limit: 20, offset: 0) { id } }
  1. Simplify query:
# Instead of deeply nested
query { posts { author { posts { author { ... } } } } }
# Use separate queries
query { posts { authorId } }
query { users(ids: [...]) { name } }

Error example:

Error: pool exhausted
-> no connections available after 30s

Cause: Too many concurrent queries.

Fix:

# Increase pool size
[database]
pool_max = 100 # Increase from default
# Or use external pooling
# PgBouncer, pgpool-II

Symptom: OOM errors, high memory usage.

Diagnosis:

Terminal window
# Check process memory
ps aux | grep fraiseql
# Check PostgreSQL memory
SELECT pg_size_pretty(pg_database_size('mydb'));

Fixes:

  1. Limit query complexity:
[validation]
max_query_depth = 5
max_query_complexity = 500
  1. Add pagination limits:
[query_defaults]
limit = true # ensure limit argument is enabled so clients can paginate

Error:

{
"errors": [{
"message": "Invalid token"
}]
}

Causes:

  1. Token expired
  2. Wrong signing secret
  3. Malformed token

Fix:

Terminal window
# Debug token
echo $TOKEN | cut -d. -f2 | base64 -d | jq
# Check expiry
# "exp": 1704067200 (Unix timestamp)
# Verify secret matches
# Server uses JWT_SECRET env var

Error:

{
"errors": [{
"message": "Unauthorized"
}]
}

Cause: Missing or invalid Authorization header.

Fix:

Terminal window
curl -X POST http://localhost:8080/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"query": "{ users { id } }"}'

Error:

{
"errors": [{
"message": "Forbidden: missing scope read:User.email"
}]
}

Cause: Token lacks required scope.

Fix: Request token with required scopes:

# Include scope in token
jwt.encode({
"sub": user_id,
"scope": "read:User.email read:User.name"
}, secret)

Set the RUST_LOG environment variable before starting FraiseQL:

Terminal window
RUST_LOG=debug fraiseql run

Always check for partial errors:

{
"data": {
"users": [...]
},
"errors": [
{"message": "Some field failed"}
]
}
-- Log all queries (development only)
ALTER SYSTEM SET log_statement = 'all';
SELECT pg_reload_conf();
Terminal window
# Test endpoint
curl -v http://localhost:8080/graphql
# Check headers
curl -I http://localhost:8080/health
# Test with specific request
curl -X POST http://localhost:8080/graphql \
-H "Content-Type: application/json" \
-d '{"query": "{ __schema { types { name } } }"}'

If you can’t resolve an issue:

  1. Search existing issues: https://github.com/fraiseql/fraiseql/issues
  2. Check documentation: https://fraiseql.dev/docs
  3. Open an issue with:
    • FraiseQL version (fraiseql --version)
    • Error message (full stack trace)
    • Minimal reproduction
    • Expected vs actual behavior

Performance Optimization

Optimize slow queries and reduce database load in production. Performance Guide

Testing Guide

Write tests to prevent regressions and catch issues early. Testing Guide

Deployment Guide

Production configuration and deployment best practices. Deployment Guide

GitHub Issues

Search for known bugs and report new ones with your diagnostics bundle. Open an Issue

Discord Community

Get real-time help from maintainers and community members. Join Discord

Common Issues

Comprehensive reference organised by error type and symptom. Common Issues