readysite / docs / troubleshooting.md
7.4 KB
troubleshooting.md

Troubleshooting

Common issues and solutions when developing with ReadySite.

Build Errors

CGO / libsql compilation fails

Symptom: cgo: C compiler "gcc" not found or linking errors.

Cause: The database layer requires CGO for libsql/SQLite.

Fix: Install a C compiler:

# macOS
xcode-select --install

# Ubuntu/Debian
apt-get install build-essential

# Alpine (don't use for production)
apk add gcc musl-dev

Docker: Use golang:1.24-bookworm for builds, debian:bookworm-slim for runtime. Alpine won't work because CGO binaries need glibc.

go build ./hosting fails with directory exists

Symptom: Build fails because hosting/ is also a directory name.

Fix: Specify an output path:

go build -o /tmp/hosting ./hosting

Module resolution errors

Symptom: cannot find module providing package github.com/readysite/readysite/pkg/...

Fix:

go mod tidy

If using a local development copy:

go mod edit -replace github.com/readysite/readysite=../readysite
go mod tidy

Database

In-memory database loses data on restart

Symptom: All data disappears when the app restarts.

Cause: No DB_PATH or DB_URL is configured, so the auto engine defaults to in-memory.

Fix: Set a database path:

DB_PATH=./data/app.db go run ./website

Remote replica sync failures

Symptom: Data appears stale or writes fail.

Cause: The replica can't reach the primary libSQL server.

Fix:

  1. Check DB_URL and DB_TOKEN are correct
  2. Verify network connectivity to the primary
  3. Force a sync: models.DB.Sync()

"database is locked" errors

Symptom: Concurrent writes fail with lock errors.

Cause: SQLite allows one writer at a time. This is rare with the embedded engine but can happen under heavy load.

Fix: This usually resolves itself. If persistent, check for:

  • Long-running transactions
  • Unclosed database connections
  • Multiple processes writing to the same file

Templates

Template not found

Symptom: template "page.html" not found or blank page.

Cause: Templates are referenced by filename only, not path.

Fix:

<!-- Correct -->
{{template "card.html" .}}

<!-- Wrong -->
{{template "partials/card.html" .}}

Templates in views/layouts/ and views/partials/ are pre-loaded at startup. All other .html files under views/ are loaded on-demand by filename.

Controller methods not accessible in templates

Symptom: {{home.Method}} returns nothing or errors.

Cause: The method might not be public (capitalized) or the controller name is wrong.

Fix:

  1. Ensure the method name starts with a capital letter
  2. Use the controller name from the factory function: {{controllerName.Method}}
  3. Don't use dot notation: {{home.Method}} not {{.home.Method}}

Template changes not reflecting

Symptom: Edits to templates don't appear after refresh.

Cause: Layout and partial templates are cached at startup.

Fix: Restart the application. In development, non-layout/partial templates reload automatically.

Frontend / esbuild

HMR not working in development

Symptom: React component changes don't hot-reload.

Cause: HMR is disabled in production mode.

Fix:

  1. Make sure ENV is not set to production
  2. Check the browser console for WebSocket connection errors
  3. Verify esbuild is running (check terminal output)

esbuild "Could not resolve" errors

Symptom: Build fails with module resolution errors.

Fix:

  1. Run npm install in the app directory
  2. Check that package.json includes the dependency
  3. Verify the Include paths in your bundler config match your file structure:
frontend.WithBundler(&esbuild.Config{
    Entry:   "frontend/index.js",
    Include: []string{"frontend"},  // Must match actual directory
})

Node.js not found in Docker

Symptom: esbuild fails in production Docker container.

Fix: Add Node.js to your Dockerfile runtime stage:

FROM debian:bookworm-slim
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
    apt-get install -y nodejs

Authentication

AUTH_SECRET fatal error on startup

Symptom: FATAL: AUTH_SECRET must be set in production

Cause: ENV=production is set but AUTH_SECRET is empty or "change-me-in-production".

Fix:

# Generate and set a secret
export AUTH_SECRET=$(openssl rand -hex 32)

Session cookie not persisting

Symptom: User is logged out after every request.

Cause: The Secure flag is set but you're not using HTTPS.

Fix: In development, don't set ENV=production. The isSecure() helper detects HTTPS from direct TLS or X-Forwarded-Proto headers.

JWT validation fails after secret change

Symptom: All users are logged out after changing AUTH_SECRET.

Cause: Existing JWTs were signed with the old secret.

This is expected. Users will need to log in again.

Deployment

Server creation hangs

Symptom: launch --new hangs after creating the server.

Cause: SSH access isn't ready yet or SSH key isn't configured.

Fix:

  1. Ensure you have an SSH key: ~/.ssh/id_ed25519.pub or ~/.ssh/id_rsa.pub
  2. Wait — new servers can take 1-2 minutes for SSH to become available
  3. Check cloud provider dashboard for server status

Docker build fails on server

Symptom: Remote build fails during launch.

Cause: Server doesn't have enough memory or Docker isn't installed.

Fix:

  1. Use at least a small server size
  2. Build locally instead (requires Docker Desktop)
  3. Check server logs: go run ./cmd/connect docker logs

Health check failures after deploy

Symptom: Container keeps restarting after deployment.

Cause: The /health endpoint isn't responding within the timeout.

Fix:

  1. Check container logs: go run ./cmd/connect docker logs <container>
  2. Verify the health endpoint exists and returns 200
  3. Check that PORT env var matches the container's listening port
  4. Increase the health check start period if the app needs more startup time

Volume mount permissions

Symptom: App can't write to /data directory.

Cause: Volume directory doesn't exist or has wrong permissions.

Fix: Add to your setup.sh:

mkdir -p /mnt/data/myapp
chmod 755 /mnt/data/myapp

Rate Limiting

"Too many requests" during development

Symptom: Getting rate limited during local testing.

Cause: Rate limiters use r.RemoteAddr which is typically 127.0.0.1 for all local requests.

Fix: This is working as intended. Wait for the bucket to refill (typically 1 minute). For testing, restart the application to reset rate limit buckets.

AI Assistant

"API key is required" error

Symptom: AI features return assistant.ErrNoAPIKey.

Cause: No API key configured for the selected provider.

Fix: Set the API key for your provider:

  • OpenAI: Configure in website settings or pass to openai.New(key)
  • Anthropic: Configure in website settings or pass to anthropic.New(key)
  • Testing: Use mock.New(mock.Config{Response: "test"}) — no key needed

AI responses are empty

Symptom: Chat returns empty content.

Cause: The model may have returned only tool calls (no text content).

Fix: Check resp.ToolCalls — if resp.FinishReason is "tool_calls", the model wants to execute tools before responding with text.

← Back