Diagnóstico
Síntomas concretos, su causa habitual y cómo confirmarla.
Desarrollo
Variables de entorno inválidas o faltantes
Falta .env o alguna variable obligatoria.
cp .env.example .envAUTH_SECRET necesita al menos 32 caracteres:
openssl rand -base64 48Can't reach database server at localhost:5433
PostgreSQL no está levantado.
docker compose up -ddocker compose psEl puerto es 5433, no 5432, para no chocar con una instalación local de
PostgreSQL. Si cambiaste el puerto, ajusta DATABASE_URL.
Cannot find module '@/generated/prisma/client'
El cliente de Prisma no está generado. Se genera en postinstall y en build,
pero si borraste src/generated:
pnpm exec prisma generateEl cronómetro no avanza
Comprueba que el servicio está IN_PROGRESS y que el empleado tiene una
sesión abierta. El cronómetro sólo corre para quien está trabajando.
Las fotos no suben en desarrollo
MinIO no está corriendo o el bucket no existe:
docker compose up -ddocker compose logs storage-initDebe decir «Bucket royal-clean-evidence listo y privado». Consola web en
http://localhost:9001 (royalclean / royalclean_dev_secret).
This module cannot be imported from a Client Component
Un componente cliente está importando un módulo server-only. Suele pasar con
las etiquetas: modules/audit/service.ts es server-only, pero
modules/audit/labels.ts no. Importa desde el módulo compartido.
Los tests de integración no encuentran la base
Falta crearla:
docker compose exec db psql -U royalclean -d postgres -c "CREATE DATABASE royalclean_test OWNER royalclean;"El servidor de desarrollo se queda colgado
Ocurre tras suspender el equipo o dejarlo mucho tiempo inactivo. Reinícialo:
pnpm devSi el puerto sigue ocupado, localiza el proceso que escucha en el 3000 y termínalo antes de volver a arrancar.
Producción
El contenedor no arranca
Mira los logs. Las causas habituales, en orden:
1. Fallo de migración.
Error: P3009 migrate found failed migrationsUna migración anterior quedó a medias. Revisa la tabla _prisma_migrations,
corrige el estado y despliega de nuevo. Si la base quedó inconsistente, restaura
el respaldo (OPERATIONS.md).
2. Variable faltante.
Variables de entorno inválidas o faltantes:
- AUTH_SECRET: ...Revisa la configuración en Dokploy.
3. Base de datos inalcanzable.
Can't reach database serverEl DATABASE_URL debe usar el host interno de Docker (el nombre del
servicio), no localhost ni una IP pública.
exec ./entrypoint.sh: no such file or directory
El script tiene finales de línea CRLF. El Dockerfile ya los normaliza y
.gitattributes fuerza LF, así que esto sólo pasa si el archivo se copió sin
pasar por git. Reconstruye la imagen.
El healthcheck falla pero la app responde
/api/health verifica la aplicación y la base de datos. Un 503 significa
que la aplicación vive pero no alcanza PostgreSQL.
docker psdocker logs royalclean-dbLas fotos no cargan en producción
Comprueba las variables de R2. Si faltan, la aplicación arranca igual pero la evidencia falla con un mensaje claro.
Comprueba el token. Necesita Object Read & Write sobre el bucket.
Comprueba el bucket. Debe existir y llamarse igual que R2_BUCKET_NAME.
Si una imagen concreta devuelve 410, esa evidencia expiró por retención o fue eliminada: es el comportamiento esperado.
Failed to fetch Inter from Google Fonts al construir
No debería ocurrir: el proyecto usa la pila de fuentes del sistema
precisamente para no depender de esa red (DECISIONS.md DEC-015).
Si aparece, alguien reintrodujo next/font/google.
El despliegue tarda mucho
El primer build compila todo. Los siguientes aprovechan la caché de capas
siempre que package.json y pnpm-lock.yaml no cambien.
Datos
«El empleado dice que trabajó más horas»
Revisa Servicios → (servicio) → Tiempos. Verás cada sesión con su inicio y su fin.
Causas frecuentes:
- Olvidó pulsar «Iniciar servicio» al llegar.
- Olvidó finalizar y la sesión quedó abierta (aparece la alerta de tiempo).
- Retomó el trabajo y no cuenta la segunda sesión.
Corrige con Corregir, indicando el motivo. Queda auditado.
«El margen de este servicio parece muy alto»
Probablemente falten costos internos de insumos. Cuando ocurre, el sistema lo dice explícitamente: «2 insumos no tienen costo interno registrado».
El sistema nunca asume que un costo desconocido vale cero. Registra los costos y la cifra dejará de ser parcial.
«Cambié la tarifa y los servicios viejos no cambiaron»
Es el comportamiento correcto. La tarifa se congela al asignar (BUSINESS_RULES.md §6). Un servicio de agosto se paga a la tarifa de agosto.
Lo mismo vale para el precio de las propiedades y para las plantillas de tareas.
«Corregí unas horas y el pago no cambió»
También es correcto. Al registrar un pago, el desglose se congela: el recibo documenta lo que realmente se pagó.
El sistema avisa al corregir horas de un servicio ya liquidado y lo anota en auditoría. Si hay que ajustar el pago, revierte el pago y vuelve a registrarlo.
«Un empleado no puede iniciar un servicio»
Comprueba, en orden:
- ¿Está asignado a ese servicio?
- ¿El servicio está en
ASSIGNEDoIN_PROGRESS? - ¿Tiene tareas definidas?
- ¿Tiene ya trabajo abierto en otro servicio? Sólo puede tener una sesión abierta a la vez; el mensaje lo indica.
«No puedo archivar una propiedad»
Tiene un servicio en progreso. Espera a que termine: archivarla dejaría a alguien trabajando en una propiedad que la aplicación considera inexistente.
«No puedo desactivar a un empleado»
Tiene trabajo en curso. Cierra su participación primero.
Acceso
«Usuario o contraseña incorrectos» con las credenciales correctas
El mensaje es único a propósito: no revela si el usuario existe. Comprueba:
- ¿La cuenta está desactivada? En ese caso el mensaje sí es distinto.
- ¿Superó el límite de intentos? 5 fallos por usuario en 15 minutos.
- Restablece la contraseña desde Empleados.
«Demasiados intentos fallidos»
Rate limiting. Espera 15 minutos o restablece la contraseña, lo que también limpia los intentos previos.
«Debe cambiar su contraseña» y no puede salir de esa pantalla
Es lo esperado tras un restablecimiento. Debe elegir una contraseña propia para continuar.
Un empleado ve 404 en un servicio que sí existe
Correcto: no está asignado. El sistema devuelve 404 en lugar de 403 para no confirmar que el recurso existe (AUTHORIZATION.md).
Cómo pedir ayuda
Al reportar un problema, incluye:
- Qué intentabas hacer.
- Qué esperabas y qué pasó.
- El mensaje exacto.
- Rol del usuario e identificador del servicio si aplica.
- Los logs relevantes:
docker logs royalclean-app 2>&1 | tail -50La auditoría (/admin/auditoria) suele responder «quién cambió qué y cuándo»
sin necesidad de mirar logs.