Common issues and solutions for Veritas Kanban. Can't find your issue? Open a Discussion or file an issue.
- Installation & Build
- Authentication & Rate Limiting
- Networking & Proxies
- WebSocket Issues
- Docker
- Agent Integration
- UI & Frontend
- Data & Storage
- Useful Commands
- Dev Reliability (ports, hangs, and restarts)
planning was removed entirely as a TaskStatus (process/UI heavy and overkill for an agent-first Kanban).
Valid statuses are:
todoin-progressblockeddone
If you need “planning”, put it in the task body/checklist or treat it as agent-internal planning — not a board column.
If the UI is acting hung or the API is returning unexpected 404s, run:
pnpm dev:cleanThis:
- frees ports 3001 (server) and 3000 (web)
- kills stale dev watchers for this repo (
tsx watch,vite,concurrently) - restarts
pnpm dev
VK provides a canonical health endpoint for tooling:
curl -s http://localhost:3001/api/healthExpected: HTTP 200 JSON like:
{ "ok": true, "service": "veritas-kanban", "version": "1.x.x" }If you want VK to auto-restart when unhealthy during dev:
pnpm dev:watchdogEnvironment variables:
WATCHDOG_INTERVAL_SECONDS(default 30)WATCHDOG_FAIL_THRESHOLD(default 3)
Note: watchdog is for local dev convenience. For production, prefer a real supervisor (pm2/docker) with health checks.
TypeScript errors during initial pnpm install or pnpm build usually resolve on a second run. This happens when shared type packages aren't built yet.
# Clean build from scratch
pnpm clean # if available
rm -rf node_modules
pnpm install
pnpm buildIf errors persist, check your Node.js version — Node 22+ is required:
node -v # Should be v22.x or higherVeritas Kanban uses pnpm workspaces. Install it first:
npm install -g pnpm
# or
corepack enable && corepack prepare pnpm@latest --activate# Check what's using port 3001 (API) or 3000 (Web)
lsof -i :3001
lsof -i :3000
# Change ports in server/.env
PORT=3002 # API portUpdate CORS_ORIGINS in .env if you change the web port.
This is the most common issue for local development and SSH tunnel users.
The auth rate limiter defaults to 10–15 requests per 15 minutes. Normal UI usage (page loads, tab refreshes, WebSocket reconnections) can exhaust this quickly.
Fix 1: Update to the latest version
This was fixed — authRateLimit now exempts localhost requests automatically (same as apiRateLimit). Pull the latest and restart.
Note: If you're behind an SSH tunnel or reverse proxy,
req.ipmay not resolve to127.0.0.1. See SSH Tunnel / Proxy Issues below.
Fix 2: Increase the auth rate limit
In server/src/middleware/rate-limit.ts, increase max for the auth limiter:
max: 100; // default is 10-15, increase for developmentFix 3: Restart the server
Rate limit counters are stored in-memory and reset on restart:
# Ctrl+C the running server, then:
pnpm devFix 4: Disable auth entirely (development only)
In server/.env:
VERITAS_AUTH_ENABLED=falseThe server warns at startup if VERITAS_ADMIN_KEY is less than 32 characters. Generate a strong key:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"Check the auth diagnostics endpoint:
curl -H "X-API-Key: your-admin-key" http://localhost:3001/api/auth/diagnosticsVerify your .env has the correct key format:
# API keys format: name:key:role,name2:key2:role2
VERITAS_API_KEYS=my-agent:my-secret-key:agentSymptom: ValidationError: The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false
Cause: Running behind a reverse proxy (nginx, Caddy, Traefik, Synology DSM) without configuring trust proxy.
Fix: Set the TRUST_PROXY environment variable:
TRUST_PROXY=1 # Trust one proxy hop (most common)See Deployment Guide for full configuration options.
# 1. Authorization header (Bearer token)
curl -H "Authorization: Bearer your-api-key" http://localhost:3001/api/tasks
# 2. X-API-Key header
curl -H "X-API-Key: your-api-key" http://localhost:3001/api/tasks
# 3. Query parameter (useful for WebSocket connections)
ws://localhost:3001/ws?api_key=your-api-keyWhen accessing Veritas Kanban through an SSH tunnel, your requests may appear as ::ffff:127.0.0.1 (IPv4-mapped IPv6) instead of 127.0.0.1, causing localhost exemptions to fail.
Fix 1: Force IPv4 binding
# In your .env or when starting the server:
HOST=127.0.0.1 pnpm devFix 2: Verify your SSH tunnel binds to 127.0.0.1
# Correct — binds to localhost explicitly
ssh -L 127.0.0.1:3001:127.0.0.1:3001 user@server
# May cause issues — binds to all interfaces
ssh -L 3001:localhost:3001 user@server
ssh -L 0.0.0.0:3001:127.0.0.1:3001 user@serverFix 3: Debug the detected IP
Add a temporary log to see what IP the server receives:
// In your rate limiter or middleware:
console.log('Client IP:', req.ip, req.connection.remoteAddress);If you see CORS errors in the browser console, update CORS_ORIGINS in server/.env:
# Add your frontend URL (comma-separated, no trailing slashes)
CORS_ORIGINS=http://localhost:3000,http://localhost:5173,http://your-ip:3000,http://your-hostname:5173When using hostname access on LAN (for example http://manfredclaw:5173), include that hostname origin explicitly.
If the web dev server rejects LAN hostname access, configure Vite host allowlist in web/.env:
VITE_HOST=0.0.0.0
VITE_ALLOWED_HOSTS=your-hostname,your-hostname.local,your-ipYou can allow all hosts for trusted LAN-only environments:
VITE_ALLOWED_HOSTS=*By default, the server binds to localhost. To access from other machines:
# In server/.env
HOST=0.0.0.0Update both CORS and Vite allowlist to include the IP/hostname you'll access from:
# server/.env
CORS_ORIGINS=http://localhost:3000,http://localhost:5173,http://your-ip:3000,http://your-hostname:5173
# web/.env
VITE_HOST=0.0.0.0
VITE_ALLOWED_HOSTS=your-hostname,your-hostname.local,your-ip- Verify
CORS_ORIGINSincludes your frontend URL - If behind a reverse proxy, ensure WebSocket upgrade headers are forwarded:
nginx:
location /ws {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400; # WebSocket connections are long-lived
}Caddy:
reverse_proxy /ws 127.0.0.1:3001Caddy handles WebSocket upgrades automatically.
- Check proxy timeout settings (must be longer than the WebSocket heartbeat interval)
- The client automatically reconnects with exponential backoff
- TanStack Query polling increases when WebSocket is disconnected, decreases when reconnected
# Check logs
docker compose logs veritas-kanban
# Common causes:
# - Port 3001 already in use → change port mapping in docker-compose.yml
# - Permission denied on volume → check UID 1001 ownershipThe container runs as non-root (UID 1001). Fix volume permissions:
# On the host machine
sudo chown -R 1001:1001 ./dataSymptom: Container starts but crashes immediately with EACCES: permission denied when trying to create .veritas-kanban directory.
Root cause: Services use process.cwd()/.. to resolve the project root. With WORKDIR /app, this resolves to / (filesystem root), which is not writable by the non-root user.
Fix: Version 2.1.2 changed the production WORKDIR to /app/server and ensured /app/tasks and /app/server are writable. Update to v2.1.2+ to resolve:
git pull origin main
docker compose build --no-cache
docker compose up -dIf you've customized the Dockerfile, ensure:
WORKDIR /app/server(not/app)- Directories
/app/tasksand/app/serverare owned by UID 1001
docker compose build --no-cache
docker compose up -d- Verify the server is running:
curl http://localhost:3001/api/health - Check your agent's API key has the
agentrole:VERITAS_API_KEYS=my-agent:my-secret-key:agent
- For agents running in Docker/containers, use
host.docker.internal:3001instead oflocalhost:3001
The CLI depends on the built shared package. If npm link ran before the packages were built, rebuild and relink:
pnpm --filter @veritas-kanban/shared build
pnpm --filter @veritas-kanban/cli build
cd cli
npm linkLocalhost bypass commonly grants read-only access. Create an agent key in server/.env, restart the server, and pass the key to the CLI or MCP client:
VERITAS_API_KEYS=local-agent:replace-with-a-long-secret:agentexport VK_API_URL=http://localhost:3001
export VK_API_KEY=replace-with-a-long-secretFor MCP, put VK_API_KEY in the MCP server env block. Avoid using the admin key unless you need admin-only endpoints.
OpenClaw is optional. Use the board-only path in Setup Paths, then add OpenClaw only if you want OpenClaw to execute tasks, use the browser relay, or receive Squad Chat wake events.
No. The agent system is platform-agnostic. The board doesn't call LLMs directly — it provides a REST API that any agent can call. Whether you're using Claude, GPT, Kimi, Gemini, Llama, or a custom model, if your agent can make HTTP requests, it can drive the board.
The agent dropdown in the UI is for labeling/tracking purposes. It doesn't affect functionality.
Verify the MCP server config in your Claude Desktop settings:
{
"mcpServers": {
"veritas-kanban": {
"command": "node",
"args": ["/path/to/veritas-kanban/mcp/dist/index.js"],
"env": {
"VK_API_URL": "http://localhost:3001",
"VK_API_KEY": "your-agent-key"
}
}
}
}Build the MCP server first: cd mcp && pnpm build
1. Restart OpenClaw after MCP config changes
MCP servers are discovered at gateway startup, not dynamically. After adding or modifying the MCP server configuration in your claude_desktop_config.json or OpenClaw config, you must restart the OpenClaw gateway:
# Restart the OpenClaw gateway
openclaw gateway restart
# Verify gateway is running
openclaw gateway status
# Check gateway logs for MCP discovery errors (if any)
tail -f ~/.openclaw/logs/gateway.logCommon mistakes:
- Editing config but forgetting to restart → MCP server won't appear
- Restarting just Claude Desktop/Cursor → doesn't reload OpenClaw's MCP registry
- Config syntax errors → check logs for JSON parsing errors
2. Verify MCP discovery and tools after restart
After restarting, confirm that Veritas Kanban was successfully discovered and all tools are available:
# List all discovered MCP servers
openclaw mcp list
# Expected output should include:
# veritas-kanban | 36 tools | http://localhost:3001
# View available tools from Veritas Kanban
openclaw mcp tools veritas-kanban
# Test a specific tool (should return JSON schema)
openclaw mcp describe veritas-kanban vk_list_tasksIf Veritas Kanban doesn't appear in the list:
- Verify the MCP server config path is absolute (not relative):
/Users/you/path/to/veritas-kanban/mcp/dist/index.js - Check that
mcp/dist/index.jsexists:ls -la /path/to/veritas-kanban/mcp/dist/ - Build the MCP server if missing:
cd mcp && pnpm build - Check OpenClaw logs for startup errors:
~/.openclaw/logs/mcp.log
If the tool count is wrong (not 36 tools):
- MCP server may have started but failed to initialize properly
- Check VK API is accessible:
curl http://localhost:3001/api/health - Verify API key is set in MCP config env vars
- Review MCP server logs for initialization errors
If reads work but write tools return 401 or 403:
- Confirm
VK_API_KEYis set in the MCP client env block - Confirm the same key is present in
VERITAS_API_KEYSwith theagentrole - Restart both
pnpm devand the MCP client after env changes
Squad Chat stores local messages and streams them to connected UI clients. It does not wake an external process by itself. Configure Settings -> Notifications -> Squad Chat Webhook only when you want outbound delivery through a generic webhook or OpenClaw Direct.
Notification delivery channels are optional. Local notifications, broadcasts, and Squad Chat can work while external webhook delivery is disabled. Use /api/broadcasts for durable system-wide messages and verify delivery-specific settings before expecting an external wake or push.
3. Gather diagnostics bundle when reporting issues
If MCP connection fails after following steps 1-2, collect this full diagnostics bundle to share when reporting an issue:
# === System & Version Info ===
echo "=== OpenClaw Version ===" && openclaw --version
echo "=== Node.js Version ===" && node -v
echo "=== OS Info ===" && uname -a
# === Veritas Kanban Health ===
echo "=== VK Health Check ===" && curl -s http://localhost:3001/api/health | jq .
echo "=== VK Version ===" && cat ~/Projects/veritas-kanban/package.json | jq -r '.version'
# === MCP Discovery Status ===
echo "=== MCP Server List ===" && openclaw mcp list
echo "=== VK MCP Tools ===" && openclaw mcp tools veritas-kanban || echo "Server not discovered"
# === OpenClaw Logs (MCP specific) ===
echo "=== MCP Server Logs (last 50 lines) ==="
# macOS/Linux:
tail -n 50 ~/.openclaw/logs/mcp.log 2>/dev/null || echo "MCP log not found"
# Windows (PowerShell):
# Get-Content $env:USERPROFILE\.openclaw\logs\mcp.log -Tail 50
# === Gateway Logs ===
echo "=== Gateway Logs (last 50 lines) ==="
tail -n 50 ~/.openclaw/logs/gateway.log 2>/dev/null || echo "Gateway log not found"
# === MCP Config Validation ===
echo "=== MCP Config (sanitized) ==="
# macOS:
cat ~/Library/Application\ Support/Claude/claude_desktop_config.json | jq '.mcpServers["veritas-kanban"]' || echo "Config not found"
# Linux:
cat ~/.config/claude/claude_desktop_config.json | jq '.mcpServers["veritas-kanban"]' 2>/dev/null || echo "Config not found"
# === API Accessibility Test ===
echo "=== VK API Access Test ==="
curl -s -H "X-API-Key: test-key" http://localhost:3001/api/tasks | head -c 200
# === MCP Server File Check ===
echo "=== MCP Server Files ==="
ls -lh ~/Projects/veritas-kanban/mcp/dist/index.js 2>/dev/null || echo "MCP server not built"When reporting an issue, include:
- Full output from the diagnostics commands above
- Your sanitized MCP config (remove sensitive API keys)
- Steps to reproduce the connection failure
- Expected vs actual behavior
Privacy note: The diagnostics bundle may contain local paths and usernames. Review and redact sensitive information before sharing publicly.
- Check the browser console for errors (F12 → Console)
- Verify both services are running:
- Try a hard refresh:
Ctrl+Shift+R(Windows/Linux) orCmd+Shift+R(Mac)
- Tooltips can interfere with drag detection — they're automatically suppressed during drag operations
- If using a touch device, long-press to initiate drag
- Check browser console for JavaScript errors
The UI follows your system theme preference. To force a theme, check Settings → Appearance.
Tasks are Markdown files with YAML frontmatter stored in the tasks/ directory:
tasks/
├── active/ # Current tasks (todo, in-progress, blocked)
├── archive/ # Archived/completed tasks
└── templates/ # Task templates
You can edit them directly with any text editor, grep them, or version them with git.
# Simple backup
cp -r tasks/ tasks-backup-$(date +%Y%m%d)/
# Or use git (recommended)
cd tasks && git init && git add -A && git commit -m "backup"Copy your backed-up task files back into tasks/active/ and restart the server. The in-memory cache rebuilds from disk on startup.
# Remove all tasks
rm tasks/active/task_*.md
# Re-seed with examples (optional)
pnpm seed# Development
pnpm dev # Start both web and API in dev mode
pnpm build # Production build
pnpm test # Run all tests
pnpm test:e2e # Run Playwright E2E tests
# CLI
pnpm cli list # List tasks from terminal
pnpm cli create # Create a task
pnpm cli update # Update a task
# Health checks
curl http://localhost:3001/api/health # Server health
curl http://localhost:3001/api/auth/diagnostics # Auth diagnostics (needs admin key)
# API docs
open http://localhost:3001/api-docs # Swagger UI- 💬 GitHub Discussions — ask the community
- 🐛 GitHub Issues — report a bug
- 📖 Deployment Guide — production setup
- 📖 Features Guide — full feature documentation
- 🔒 Security Guide — auth, rate limiting, API keys