Volver a la documentación
Guía 12

Troubleshooting

Síntomas comunes, causa, resolución. Referencias file:line y cross-link a los docs.

6 min de lectura

Síntomas comunes, causa, resolución. Referencias file:line y cross-link a los docs.

Arranque & config

El servidor sale inmediatamente con process.exit(1)

  • Causa: validación env Zod fallida (src/config/env.ts).
  • Fix: revisa los logs - indican la variable inválida. Verifica JWT_SECRET (oblig.), COLLECTOR_SECRET (oblig.), DATABASE_URL, puertos. Compara con .env.example.

COLLECTOR_SECRET mismatch entre server y collector

  • Síntoma: el collector no consigue notificar el status del documento; el upload queda "processing".
  • Fix: establece el mismo COLLECTOR_SECRET en el .env raíz (config única - la capa .env per-package se eliminó en v0.22). Comparación constant-time → error 401 silencioso.

WIDGET_API_KEY mismatch widget↔server

  • Síntoma: el widget no carga config / chat 401 desde el servidor.
  • Fix: misma key en el .env raíz (config única). Sin key, el cache-bust push es no-op (TTL 5 min).

Config modificada desde la UI sin efecto

  • Causa: las claves ALWAYS_READONLY (JWT_SECRET, DATABASE_URL, puertos, URL) son rechazadas por el bulk settings; las demás siguen DB > ENV > Default.
  • Fix: para claves readonly, modifica .env + restart. PUT /api/system/settings devuelve { rejected: [...] } - revisa ese array.

Database

Migraciones en conflicto / reset dev

  • Fix: en dev con DB desechable, reset con pnpm db:migrate:reset:guard (requiere PRISMA_MIGRATE_RESET_CONFIRM=yes o --force-accept-data-loss - nunca en producción). Deploy con guard: pnpm db:migrate:guard (rechaza migraciones destructivas sin consentimiento explícito). Verifica PostgreSQL 16 y DATABASE_URL correcta.

Restore backup no atómico / datos parciales

  • Causa: el restore usa psql --single-transaction --set ON_ERROR_STOP=on; si falla hace rollback completo.
  • Fix: revisa los logs psql; safety backup pre-restore (runSafetyBackup). Usa /restore/:logId/dry-run antes del restore real.

RAG & embedding

Vector search devuelve 0 resultados pero FTS funciona

  • Causa: guard D-01 - EMBEDDING_MODEL actual ≠ embeddingModel de los Document (p. ej. modelo cambiado tras el upload): el leg vector se salta y la búsqueda degrada a FTS-only.
  • Fix: re-embed via POST /api/system/reembed-documents (admin, opcional workspaceId/documentIds) para re-embeddear los chunks con el modelo actual; si solo necesitas reconstruir el índice FTS desde el vector DB: POST /api/system/reindex-documents. Ambos admin-only, también desde Settings → Maintenance.

RAG degradado en el widget (status: rag-degraded)

  • Causa: pre-search RAG fallida (collector down, whitelist workspace vacía) o 0 resultados de la búsqueda de los workspace vinculados.
  • Fix: verifica GET /api/health/rag; revisa WidgetWorkspace para el widget (GET /api/widgets/:id/workspaces); confirma collector up (GET :3210/api/health).

LanceDB table missing / query error

  • Causa: tabla per-workspace ws_<name>_<shortId> no creada o storage movido.
  • Fix: verifica que el STORAGE_PATH del collector está invariado; reindex wiki/documentos.

Agent & LLM

Agent abort: unknown_tool_breaker

  • Causa: circuit breaker BOT-03 - 3 skills desconocidas consecutivas / 5 en total. A menudo un modelo que alucina tools no registrados.
  • Fix: usa un modelo más capaz o reduce las skills habilitadas; verifica la conexión MCP enabled y las skills registradas (mcp_<conn>_<tool>).

Agent abort: wallclock / token_budget / context_overflow

  • Fix: sube los env AGENT_WALLCLOCK_TIMEOUT_MS (default 600000), AGENT_MAX_TOTAL_TOKENS (200000), AGENT_MAX_CONTEXT_BYTES (500000). Para tareas simples bájalos para evitar stalls. Ver 03 - Configuration § Agent watchdog.

Modelo no responde / timeout LLM local

  • Causa: Ollama down o modelo no pulleado; LLM_TIMEOUT=0 = sin timeout (LLM locales lentos).
  • Fix: ollama list / ollama pull gemma4:latest; verifica OLLAMA_BASE_URL (http://ollama:11434 en el compose). Fallback provider: revisa Provider.isAvailable (polling 30s).

Fallback provider no disparado

  • Causa: ningún provider alternativo disponible (isAvailable=false) o default global no definido.
  • Fix: añade provider (POST /api/providers), set default (PUT /:id/set-default), verifica el tag deriveCapabilities. Frontend fallback 3-tier con toast Undo.

Widget

El widget no carga / iframe vacío

  • Causa: allowedOrigins no incluye el origen host → CORS dinámico fail-closed.
  • Fix: añade el origen a Widget.allowedOrigins (string CSV, max 2000 char). Verifica que GET /api/config/:widgetId responda.

Lead capture 403

  • Causa: config.leadCaptureEnabled=false para ese widget.
  • Fix: habilítalo en el modelo Widget (admin UI o API).

Rate limit 429 en el widget

  • Causa: cadena de limiter - widgetDailyMessageLimiter (5/24h por widget+IP, override sessionLimitPerDay), widgetChatLimiter (30/min por widgetId, override rateLimitPerMinute), widgetSessionLimiter (50 creaciones de sesión/día por IP), widgetLeadLimiter (3/h por IP).
  • Fix: evalúa los overrides per-widget (rateLimitPerMinute/sessionLimitPerDay); revisa qué limiter ha triggerado (header Retry-After / body error).

MCP

Instalación marketplace 201 pero tools no disponibles

  • Causa: connectMCPServer es fire-and-forget; el fallo se loguea pero no se propaga.
  • Fix: POST /api/mcp-connections/:id/test (10s, devuelve {success, toolCount, error}). Verifica el transport fallback D-09; revisa activeConnections via GET /api/mcp-connections/statuses.

MCP deshabilitado automáticamente

  • Causa: ¿auto-disable estilo webhook? No - la conexión MCP permanece enabled; es el webhook el que se auto-deshabilita tras 10 fallos consecutivos. Para MCP, el health check 30-min establece healthStatus (stale/down) pero no deshabilita la conexión.
  • Fix: para el webhook, reactiva manualmente; para MCP, el badge health es informativo.

Tool MCP no usado en una chat

  • Causa: pin per-chat activos que excluyen la conexión, o conexión disabled.
  • Fix: GET /api/chats/:chatId/pins; verifica resolveSkillsForChat (sin pin → todas las conexiones enabled del workspace).

Licencia

402 Payment Required en una feature

  • Causa: requireFeature(flag) o requireFeatureLimit ha gateado (Community).
  • Fix: establece LICENSE_KEY Enterprise, o quédate en Community con los límites. El body error incluye feature, tier, limit?, current?.

Enterprise expirado en runtime

  • Comportamiento: graceful degradation a Community (sin restart); warn en los logs.
  • Fix: renueva LICENSE_KEY; getLicenseInfo() relee en runtime.

Seguridad & audit

Audit log no escribe

  • Causa: el audit log es un módulo Enterprise - en Community logEvent es un no-op (el delegado de escritura no está registrado), así que ningún evento se registra.
  • Fix: Enterprise para audit log + inmutabilidad (audit_log_immutable). Verifica el entityType correcto en los filtros (GET /api/event-logs). Los webhooks de evento salen igualmente en Community (fire-and-forget).

DLP no redacta PII

  • Causa: DLP_ENABLED=false via settings (el default en v0.22 es "true" - alguien lo desactivó), o un rol en DLP_BYPASS_ROLES que lo exime del scan.
  • Fix: verifica/establece DLP_ENABLED=true via settings. Redaction sobre 10 patrones built-in database-backed: los 6 originales (email, credit_card, ssn, api_key, aws_key, private_key) más los 4 EU/IT (it_vat_iva, it_codice_fiscale, iban, eu_phone - este último seedeado DISABLED para revisión admin); patrones custom hasta 50 via el panel DLP Patterns. SSE done → dlp_matches (el frontend muestra la DLPNotice bajo el mensaje).

Backup

Job backup queda "running" para siempre

  • Causa: worker muerto sin cleanup; mutex DB BackupLog.status="running".
  • Fix: cleanStaleLocks marca running >2h como failed en el próximo bootstrap. Reinicia el servidor para triggerarlo, o actualiza manualmente el status.

Checksum mismatch al restore

  • Causa: archivo corrupto / upload parcial.
  • Fix: SHA-256 streaming calculado en el upload; verifica el fichero destino. Restaura desde el log siguiente.

Discrepancias documentales conocidas

Doc diceCódigo diceFuente de verdad
"28 permissions" / "27"31 permisos (PERMISSION_NAMES)código
"12 menu sections"13 (MENU_SECTIONS, +uploads)código
"7" languages i18n8 app locales (en, it, ru, de, fr, es, zh, pt)i18n/locales/
API-key auth (esquema antiguo)HMAC-SHA256 sk- keys (key_hash + API_KEY_HMAC_SECRET)services/apiKeyService.ts
--profile enterprise composeno definido explícitamenteLICENSE_KEY activa Enterprise

Health check rápido

bash
curl localhost:3000/api/health        # { database, collector, disk }
curl localhost:3000/api/health/rag    # estado RAG
curl localhost:3210/api/health        # collector
curl localhost:3211/health            # widget