How to Debug Issues in Kaneo: Complete Troubleshooting Guide for the Self-Hosted Platform

To debug issues in Kaneo, verify your .env configuration against the Environment Setup Guide, check the browser console for CORS errors using the parseApiError helper, trace API HTTPException throws in the Hono backend, and confirm WebSocket adapter initialization in the startup logs.

Kaneo is a self-hosted project-management platform built as a pnpm monorepo with a Hono API (apps/api) and React-Vite frontend (apps/web). When components fail to communicate or services refuse to start, understanding the specific error-handling paths in the source code allows you to debug issues in Kaneo efficiently without guesswork.

Common Failure Areas in Kaneo

CORS and Network Errors

Symptoms include "Failed to fetch" or "CORS" errors in the browser console with API requests returning 0 status. The frontend categorizes these via parseApiError in apps/web/src/lib/error-handler.ts. This utility checks error messages and returns specific troubleshooting steps through getCorsTroubleshootingSteps().

Database Connection Failures

When the API fails to start with "Database connection failed" logs, check apps/api/src/database/* and the startup sequence in apps/api/src/index.ts. Verify the DATABASE_URL and derived POSTGRES_* variables in your .env file. Migrations run automatically on startup and abort the server if they fail.

Authentication and Permission Errors

"401 Unauthorized" or "403 Forbidden" responses originate from apps/api/src/utils/validate-workspace-access.ts. This utility validates user roles and workspace membership, throwing HTTPException with specific messages when access is denied.

WebSocket Broadcasting Issues

Real-time updates depend on the adapter initialized in apps/api/src/ws/index.ts. The system logs which adapter is active (in-memory or Redis) via:

console.log(`📡 WebSockets Initialized using: "${adapter.constructor.name}"`);

If using Redis, confirm REDIS_URL, REDIS_SENTINELS, or REDIS_CLUSTER_NODES are set correctly in the environment.

Step-by-Step Debugging Workflow

  1. Verify Environment Configuration

    Check that .env contains all required variables: KANEO_CLIENT_URL, KANEO_API_URL, AUTH_SECRET, and DATABASE_URL. See the Environment Setup Guide for the complete list.

  2. Monitor Startup Logs

    Run pnpm dev and watch the console. The API prints its configuration on startup, while the web app logs the Vite dev server address.

  3. Inspect Browser Console Errors

    Open DevTools and check for network failures. The frontend uses parseApiError to classify errors:

    // apps/web/src/lib/error-handler.ts
    if (error.message.includes("Failed to fetch") || error.message.includes("CORS")) {
      return { type: "cors", message: "..." };
    }
  4. Trace API Exception Paths

    Look for HTTPException throws in the backend. For example, workspace validation:

    // apps/api/src/utils/validate-workspace-access.ts
    if (membership.length === 0) {
      throw new HTTPException(403, { message: "You don't have access to this workspace" });
    }
  5. Validate WebSocket Adapter

    Check the logs for the broadcast adapter initialization message. If real-time updates fail, verify Redis configuration variables or use the in-memory adapter for local development.

  6. Check Migration Status

    Migration files live in apps/api/src/migrations/. Failed migrations abort the server and print stack traces in the terminal.

  7. Isolate the Failure

    Test the API independently using pnpm --filter @kaneo/api dev and curl or Postman before adding the frontend layer.

Key Code Patterns for Debugging

Parsing Frontend Errors

import { parseApiError, getCorsTroubleshootingSteps } from "@/lib/error-handler";

try {
  const res = await fetch("/api/task");
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
} catch (e) {
  const err = parseApiError(e);
  if (err.type === "cors") {
    console.table(getCorsTroubleshootingSteps());
  }
}

Validating Workspace Access

import { validateWorkspaceAccess } from "@/utils/validate-workspace-access";

export async function protectedHandler(c) {
  const userId = c.get("userId");
  const workspaceId = c.req.param("workspaceId");
  await validateWorkspaceAccess(userId, workspaceId); // throws 403 if denied
  // ... authorized logic
}

Broadcasting Events

import { broadcastToProject } from "@/ws";

broadcastToProject(projectId, {
  type: "TASK_UPDATED",
  taskId,
  changes: { status: "done" },
});

Summary

Frequently Asked Questions

Why does my Kaneo API return CORS errors in the browser?

CORS errors occur when the KANEO_CLIENT_URL and KANEO_API_URL variables are misconfigured or when the API cannot reach the client origin. Check apps/web/src/lib/error-handler.ts where parseApiError detects these failures and getCorsTroubleshootingSteps() provides specific remediation steps.

How do I verify that my database connection is working correctly?

The API validates the connection on startup in apps/api/src/index.ts. Ensure your .env contains a valid DATABASE_URL and that PostgreSQL is accessible. If migrations fail in apps/api/src/migrations/, the server aborts with a detailed stack trace in the console.

Why am I getting 403 Forbidden errors when accessing a workspace?

The validateWorkspaceAccess function in apps/api/src/utils/validate-workspace-access.ts checks user membership and roles. A 403 indicates the user ID extracted from the session lacks membership in the requested workspace, throwing an HTTPException with the message "You don't have access to this workspace".

How do I debug missing real-time updates in Kanban boards?

Real-time functionality depends on the WebSocket adapter initialized in apps/api/src/ws/index.ts. Check the startup logs for the message "📡 WebSockets Initialized using: [AdapterName]". If using Redis, verify REDIS_URL is set and reachable; otherwise, the system falls back to in-memory broadcasting which only works within a single instance.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →