Solucion de problemas
El backend no arranca
Sintoma: Error: Cannot find module '@/app/...' o similar al ejecutar pnpm backend:dev.
Causa: Los alias de rutas no se resuelven o los paths de tsconfig.json no coinciden.
Solucion: Verifica que backend-js/tsconfig.json tenga "@/*": ["./src/*"] dentro de compilerOptions.paths. Si falta, revisa que backend-js/tsconfig.json extienda la base correcta.
Variables de entorno ausentes o indefinidas
Sintoma: valores undefined en logs, errores de conexion a BD, errores de envio de email o errores JWT como secretOrPrivateKey must have a value.
Solucion:
- Copia
.env.examplea.env.localenbackend-js/. - Rellena todos los valores; no dejes valores tal cual del ejemplo.
- Reinicia el servidor de desarrollo despues de los cambios.
Variables criticas con fallback hardcodeado (inseguras en produccion, pero funcionan silenciosamente en desarrollo):
JWT_SECRET: usa un fallback conocido si no esta definidaDEFAULT_USER_PASSWORD: usa un fallback conocido si no esta definida
Variables sin fallback que fallan en tiempo de ejecucion:
RESEND_API_KEY: fallara el envio de emailsGOOGLE_DIRECTIONS_API_KEY: fallaran geocoding y optimizacion de rutas- Variables MySQL: el pool de BD fallara en la primera consulta
Errores de conexion a la base de datos
Sintoma: ECONNREFUSED, ER_ACCESS_DENIED_ERROR o Unknown database en tiempo de ejecucion.
Checklist:
- El servidor MySQL esta arrancado en
MYSQL_HOST:MYSQL_PORT. - Las credenciales
MYSQL_USER/MYSQL_PASSWORDson correctas. - La base de datos existe.
schema.sqlla crea comoerronka; ejecutaCREATE DATABASE IF NOT EXISTS erronkasi hace falta. - La variable
MYSQL_DATABASEcoincide con el nombre real (erronkavspakag; difieren entreschema.sqly.env.example). - Ajuste SSL:
backend-js/src/app/config/dbConfig.tsdefinessl: { rejectUnauthorized: false }. Si tu instancia MySQL requiere un certificado concreto, ajustalo.
Falla la comprobacion TypeScript (tsc --noEmit)
Sintoma: errores de tipos al ejecutar pnpm tsc --noEmit en backend-js/.
Causas y soluciones comunes:
| Error | Solucion |
|---|---|
Property 'X' does not exist on type 'Y' | Comprueba que la interfaz DTO y el archivo de tipos esten sincronizados |
Argument of type 'any' is not assignable | No se permite any; anade una interfaz explicita |
Cannot find module '@/app/...' | Comprueba los paths de tsconfig.json |
Error de tipo en route.ts | Verifica que el tipo devuelto por requireAuth se use correctamente |
401 en todas las peticiones despues del login
Sintoma: El login funciona (devuelve access_token), pero las llamadas API posteriores devuelven 401.
Checklist:
- El frontend guarda correctamente el access token en la cookie
access_token. - El interceptor de Axios lee la cookie y define
Authorization: Bearer <token>. - El token no esta caducado; el access token dura 15 minutos.
- El backend esta en otro origen; revisa CORS y
withCredentials: true.
El refresh token no funciona / el usuario vuelve al login
Sintoma: El usuario sale de sesion tras 15 minutos aunque SessionKeepAlive este activo.
Checklist:
- Abre DevTools -> Application -> Cookies. Confirma que existe la cookie
refresh_tokencon flagHttpOnly. - Confirma que
POST /api/auth/refreshno queda bloqueado por CORS. En desarrollo, el backend debe permitir el origen del frontend concredentials: true. - Confirma que la fila del refresh token no esta revocada ni caducada en la tabla
tokens. - Revisa el desfase horario; si servidor y cliente difieren mas que la vida del token, los tokens pueden parecer caducados al instante.
- Confirma que
withCredentials: trueesta configurado en el cliente Axios.
Errores CORS
Sintoma: falta la cabecera Access-Control-Allow-Origin o falla el preflight.
Solucion: En backend-js/next.config.ts (o middleware CORS equivalente), aseguro:
- El origen del frontend esta permitido explicitamente (no
*cuando se usan credenciales). Access-Control-Allow-Credentials: trueesta configurado.- Las peticiones preflight
OPTIONSdevuelven 200.
En produccion, ambas apps deben usar HTTPS para que funcionen cookies SameSite=None; Secure.
No se envia email tras crear paquete o cambiar estado
Sintoma: No llega ningun email, pero la operacion termina correctamente.
Checklist:
RESEND_API_KEYesta definida y es valida.- El dominio remitente (
no-reply@tolosaerronka.es) esta verificado en Resend. - Revisa el dashboard de Resend por fallos de envio o rebotes.
- Los emails de cambio de estado son condicionales; solo transiciones concretas disparan emails. Consulta Modelo de dominio para la tabla de disparadores.
Falla la creacion de rutas (error de Google Maps)
Sintoma: POST /api/routes/create devuelve 500 o un error relacionado con Directions API.
Checklist:
GOOGLE_DIRECTIONS_API_KEYesta definida y la clave tiene Directions API y Geocoding API activadas en Google Cloud Console.- La facturacion esta activa en el proyecto de Google Cloud.
- La clave API no tiene restricciones de IP/referer que bloqueen la IP del servidor backend.
- Las direcciones de los paquetes se geocodificaron correctamente al crearlos; si
latitude/longitudeson 0 o NULL, fallo el geocoding en la creacion del paquete.
Geocoding devuelve una ubicacion incorrecta
Sintoma: El paquete aparece en coordenadas incorrectas en el mapa.
Causa: Google Geocoding emparejo otra direccion, o la direccion es ambigua.
Solucion: Revisa la fila addresses del paquete en la BD. Corrige latitude/longitude manualmente si hace falta mediante una actualizacion directa en BD (actualmente no hay endpoint para editar coordenadas en bruto).
La optimizacion de ruta supera el maximo de paradas
Sintoma: La creacion de ruta se rechaza incluso con menos paquetes de los esperados.
Causa: El servicio de rutas anade paquetes arrastrados (paquetes asignados de dias anteriores para el mismo repartidor) a la lista de paradas automaticamente. El total esta limitado a 20 paradas.
Solucion: Reduce package_ids en la peticion para dejar espacio a los arrastrados, o limpia primero el backlog del repartidor.
Falta el log de estado despues de actualizar
Sintoma: GET /api/logs/listByPackage no devuelve logs despues de llamar a updateStatus.
Causa: La insercion del log ocurre en packageStatusSideEffects.service.ts. Si lanza error y se captura silenciosamente, la actualizacion de estado puede completarse sin escribir log.
Solucion: Revisa la consola del backend por errores de [packageStatusSideEffects]. Verifica que las restricciones de BD permiten insertar el log (por ejemplo, que existe el usuario changed_by).
Falla el build del frontend
Sintoma: pnpm frontend:dev falla con errores TypeScript o de modulos.
Solucion:
# Desde la raiz del monorepo:
pnpm install
pnpm --filter @repo/frontend-app tsc --noEmitLa busqueda de docs no encuentra una pagina
Sintoma: La busqueda Ctrl+K no devuelve resultados para una pagina conocida.
Causa: La busqueda es estatica y se basa en los titulos de navItems en docs/app/[lang]/layout.tsx. Si anades una pagina nueva sin anadirla a navItems, no aparecera en la busqueda.
Solucion: Anade la pagina nueva a navItems en layout.tsx y actualiza los tres diccionarios i18n. Consulta Auditoria de docs para el procedimiento completo.
Conflictos de version de pnpm
Sintoma: ERR_PNPM_WORKSPACE_PKG_NOT_FOUND o no se encuentra un script del workspace.
Solucion:
pnpm install # desde la raiz del monorepoTodos los comandos de paquetes del workspace deben ejecutarse desde la raiz del monorepo usando flags --filter o los scripts de nivel raiz de package.json.