GuíasResolución de problemasÍndice
- El frontend no es compatible con el backend
- El directorio de destino ya existe
- No se ha seleccionado backend ni frontend
- Upgrade encuentra cambios sin guardar en Git
- Upgrade termina con conflictos y código de salida 2
- Doctor no encuentra la configuración local
- Doctor detecta una clave local insegura
- Doctor detecta un entorno o modelo de producto incorrecto
- Doctor detecta una URL de PostgreSQL o Redis ausente o inválida
- Doctor no puede conectar con PostgreSQL o Redis
- Doctor detecta una URL pública o un proxy del frontend incorrectos
- El backend rechaza Redis sin TLS en staging o production
- El backend rechaza el correo sin configurar
- Checkout, Portal o webhooks de Stripe están deshabilitados
Resolución de problemas
Los mensajes siguientes proceden de la CLI y de los backends incluidos. Los
campos entre <...> representan valores que dependen del proyecto. Ejecuta los
comandos desde la raíz del proyecto generado salvo que se indique otra ruta;
los de generación se ejecutan desde su directorio padre. Los ejemplos de edición
usan PowerShell y notepad; puedes sustituirlo por tu editor habitual.
El frontend no es compatible con el backend
Mensaje de generator.js:
Error: Frontend "<frontend>" is not compatible with backend "<backend>". Missing backend capabilities: <capacidades>.
Causa: el backend no ofrece todas las capacidades exigidas por el frontend. Por ejemplo, Next.js y React Router requieren organizaciones y Stripe Billing, que Fastify no incluye.
Solución: consulta las plantillas y elige una combinación compatible; por ejemplo, FastAPI con Next.js, o Fastify con Astro sin la extensión de billing.
npx @soymanolo/create-my-saas --list
npx @soymanolo/create-my-saas mi-saas --backend fastapi --frontend nextjs
# Alternativa ligera, en otro destino:
npx @soymanolo/create-my-saas mi-sitio --backend fastify --frontend astro
El directorio de destino ya existe
Error: Destination already exists: <ruta-absoluta>
Causa: la CLI rechaza cualquier destino existente, aunque esté vacío, para no sobrescribir archivos (generator.js).
Solución: genera en una ruta nueva. Si querías actualizar un proyecto ya
generado, utiliza upgrade, no vuelvas a generarlo encima.
npx @soymanolo/create-my-saas mi-saas-nuevo --backend fastapi --frontend nextjs
# Para revisar una actualización del proyecto existente:
npx @soymanolo/create-my-saas upgrade ./mi-saas --dry-run
No se ha seleccionado backend ni frontend
Error: Select at least one template with --backend or --frontend.
Causa: se proporcionó un destino sin seleccionar ninguna capa (generator.js).
Solución: añade al menos una de las dos opciones. Puedes generar una API sola.
npx @soymanolo/create-my-saas mi-api --backend fastapi
Upgrade encuentra cambios sin guardar en Git
Error: Commit or stash your changes before upgrading (or use --allow-dirty).
Causa: upgrade detecta cambios mediante git status --porcelain, incluidos
archivos sin seguimiento, y bloquea la escritura. --dry-run permite revisar el
plan sin exigir un árbol limpio (upgrade.js).
Solución: revisa el estado y guarda temporalmente los cambios antes de aplicar la actualización. Recupera el stash después de revisar y guardar el resultado del upgrade; su recuperación también puede requerir resolver conflictos.
git status --short
npx @soymanolo/create-my-saas upgrade --dry-run
git stash push -u -m "Trabajo previo a la actualización"
npx @soymanolo/create-my-saas upgrade
git diff
--allow-dirty omite esta protección; no resuelve ni guarda los cambios previos.
Upgrade termina con conflictos y código de salida 2
El resumen contiene este encabezado (el número varía):
Con conflictos (resuélvelos antes de hacer commit) (<cantidad>):
Y esta indicación exacta:
Busca las marcas <<<<<<< en los archivos con conflictos; los binarios dejan la versión nueva en <archivo>.upgrade-new.
Causa: la versión local y la plantilla nueva modificaron el mismo contenido
y la fusión de tres vías no pudo resolverlo. La CLI devuelve 2, también en
--dry-run si el plan contiene conflictos. Sin --dry-run, ya ha escrito los
cambios y actualizado el manifiesto; no se trata de un git merge pendiente
(upgrade.js, cli.js).
Solución: si era una simulación, revisa las rutas indicadas antes de aplicar.
Si ya se aplicó, edita cada archivo listado, resuelve las marcas <<<<<<<,
======= y >>>>>>> y compara los binarios con sus .upgrade-new. Conserva la
versión elegida y elimina el archivo auxiliar tras revisarlo. No repitas el
upgrade como forma de resolver los conflictos. Revisa y prueba el resultado
antes de añadir las rutas resueltas y hacer commit.
git diff
git diff --check
git status --short
Doctor no encuentra la configuración local
Etiquetas exactas que aparecen con el prefijo FIX:
FIX Backend .env
FIX Frontend .env
FIX Local Compose .env
Causa: faltan los archivos .env de las capas seleccionadas o el de
deployment/. Cada línea continúa con la acción recomendada. Las comprobaciones
de esta sección y las siguientes proceden de
local-setup.js; doctor devuelve 1 si hay
algún fallo y muestra Local project needs attention..
Solución: ejecuta setup y comprueba los archivos sin probar los servicios.
setup conserva los .env existentes; si ya contienen valores incorrectos,
corrígelos con tu editor.
npx @soymanolo/create-my-saas setup .
npx @soymanolo/create-my-saas doctor . --no-services
Doctor detecta una clave local insegura
Etiqueta: “FIX Local SECRET_KEY is configured”.
Causa: SECRET_KEY tiene menos de 32 caracteres o contiene replace,
change-me o example.
Solución: genera una clave y copia el resultado en SECRET_KEY de
backend/.env. Si usas la API en Compose, actualiza también deployment/.env.
node -e "console.log(require('node:crypto').randomBytes(48).toString('base64url'))"
notepad backend/.env
notepad deployment/.env
npx @soymanolo/create-my-saas doctor . --no-services
Doctor detecta un entorno o modelo de producto incorrecto
Etiquetas:
FIX Backend uses development mode
FIX Product model matches <modelo>
Causa: APP_ENV no es development, o PRODUCT_MODEL no coincide con el
modelo registrado en .create-my-saas.json. doctor está orientado al desarrollo
local; no es un validador del despliegue de producción.
Solución: para el entorno local, establece APP_ENV=development y el
PRODUCT_MODEL indicado en el mensaje, también en deployment/.env si usas
Compose. No cambies el entorno de un despliegue real para satisfacer doctor.
Get-Content .create-my-saas.json
notepad backend/.env
notepad deployment/.env
npx @soymanolo/create-my-saas doctor . --no-services
Doctor detecta una URL de PostgreSQL o Redis ausente o inválida
Etiquetas (según la variable afectada):
FIX DATABASE_URL is configured
FIX REDIS_URL is configured
FIX DATABASE_URL has a valid URL
FIX REDIS_URL has a valid URL
Causa: falta la variable en backend/.env o no se puede interpretar como URL.
Solución: edita las URL para los servicios locales. FastAPI usa
postgresql+asyncpg://postgres:postgres@localhost:5432/app; NestJS y Fastify usan
postgresql://postgres:postgres@localhost:5432/app. Redis local usa
redis://localhost:6379. Sustituye credenciales, host, puerto y base si tu
instalación difiere.
notepad backend/.env
npx @soymanolo/create-my-saas doctor . --no-services
Doctor no puede conectar con PostgreSQL o Redis
Etiquetas:
FIX DATABASE_URL host responds on TCP
FIX REDIS_URL host responds on TCP
Causa: el host y puerto de la URL no responden por TCP dentro del tiempo de espera. Es habitual que todavía no se hayan arrancado los servicios locales.
Solución: desde la raíz del proyecto, arranca PostgreSQL y Redis con la
configuración local creada por setup y vuelve a comprobarlos.
cd deployment
docker compose -f compose.yaml -f compose.dev.yaml --env-file .env up -d postgres redis
cd ..
npx @soymanolo/create-my-saas doctor .
Si siguen fallando, revisa host y puerto en backend/.env. Un resultado OK
sólo confirma conectividad TCP: no valida autenticación, TLS ni migraciones.
--no-services omite la conexión, por lo que tampoco acredita disponibilidad.
Doctor detecta una URL pública o un proxy del frontend incorrectos
Etiquetas:
FIX Frontend public URL is configured
FIX Frontend API proxy matches the selected backend
Causa: la URL pública está vacía o contiene example.com, o
API_PROXY_TARGET no coincide con el backend seleccionado.
Solución: en frontend/.env, establece la URL pública local
http://localhost:3000 en la variable correspondiente: NEXT_PUBLIC_SITE_URL
para Next.js, VITE_PUBLIC_SITE_URL para React Router o PUBLIC_SITE_URL para
Astro. Para ejecución en el host, el proxy debe ser http://localhost:8000
(FastAPI), http://localhost:3001 (NestJS) o http://localhost:3002 (Fastify).
El proxy se comprueba sólo si se seleccionó backend.
notepad frontend/.env
npx @soymanolo/create-my-saas doctor . --no-services
El backend rechaza Redis sin TLS en staging o production
FastAPI y NestJS muestran:
RATE_LIMIT_ENABLED and a TLS REDIS_URL (rediss://) are required in production.
Fastify muestra:
RATE_LIMIT_ENABLED and a TLS REDIS_URL (rediss://) are required in staging and production.
Causa: en los tres backends, la validación de arranque se aplica tanto a
staging como a production, aunque los dos primeros mensajes sólo mencionen
producción. Falta Redis con TLS o está desactivado el límite distribuido.
Solución: provisiona Redis con TLS y configura en el entorno de despliegue
RATE_LIMIT_ENABLED=true y REDIS_URL=rediss://<usuario>:<clave>@<host>:<puerto>
con los datos reales del proveedor. Cambiar únicamente el prefijo de una URL no
activa TLS en el servidor. Si usas el Compose generado, edita deployment/.env
y recrea la API desde la raíz del proyecto:
notepad deployment/.env
docker compose -f deployment/compose.yaml --env-file deployment/.env up -d --force-recreate api
docker compose -f deployment/compose.yaml --env-file deployment/.env logs --tail 100 api
El override compose.dev.yaml utiliza Redis sin TLS y es exclusivamente local.
Fuentes: FastAPI settings,
NestJS config y
Fastify config.
El backend rechaza el correo sin configurar
Mensaje de arranque común a los tres backends:
EMAIL_DELIVERY_URL (HTTPS) and EMAIL_DELIVERY_TOKEN are required in staging and production.
Causa: en staging o production falta una URL HTTPS de entrega o el token.
La validación impide arrancar sin esa configuración. Además, el envío seguro
rechaza la ausencia de configuración en esos entornos: FastAPI y NestJS usan
“Secure email delivery is not configured.”; Fastify usa
“Secure email delivery is unavailable.”.
Solución: configura un servicio de correo que acepte el contrato del adaptador
del starter, con EMAIL_DELIVERY_URL=https://<endpoint-real> y
EMAIL_DELIVERY_TOKEN=<token-real>. El adaptador envía un POST JSON con to,
subject, text y, cuando corresponde, html y from, autenticado mediante
Authorization: Bearer. Añade EMAIL_FROM si el proveedor requiere remitente.
Para Compose, edita el entorno y recrea la API:
notepad deployment/.env
docker compose -f deployment/compose.yaml --env-file deployment/.env up -d --force-recreate api
docker compose -f deployment/compose.yaml --env-file deployment/.env logs --tail 100 api
En desarrollo, la ausencia de configuración puede suprimir el envío; arrancar localmente no demuestra que se entregue correo. Fuentes: las configuraciones enlazadas en el problema anterior y los adaptadores de FastAPI, NestJS y Fastify.
Checkout, Portal o webhooks de Stripe están deshabilitados
Mensajes de FastAPI y NestJS:
Stripe billing is not configured.
Stripe webhooks are not configured.
Causa: Stripe es opcional en estos dos backends, también en staging y
production. Sin configuración completa, Checkout devuelve
{"configured":false,"url":null,"sessionId":null} y Portal devuelve
{"configured":false,"url":null,"reason":"Stripe billing is not configured."}.
Los webhooks sin secreto devuelven HTTP 503 con código BILLING_NOT_CONFIGURED.
Esto no bloquea por sí solo el arranque. Fastify no incluye Stripe Billing.
Una configuración parcial sí bloquea el arranque con:
STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET must be configured together.
Solución: para habilitar cobros, configura ambas claves y un
STRIPE_PRICE_PLANS no vacío. Usa identificadores reales de precios y el secreto
del endpoint de webhooks correspondiente al mismo entorno de Stripe. Por ejemplo,
el valor de planes puede tener la forma
{"price_REAL":{"name":"pro","entitlements":{"api_calls":10000}}},
sustituyendo price_REAL. Registra el webhook de tu backend según su README y
recrea la API para cargar las variables:
notepad deployment/.env
docker compose -f deployment/compose.yaml --env-file deployment/.env up -d --force-recreate api
docker compose -f deployment/compose.yaml --env-file deployment/.env logs --tail 100 api
Si no vas a ofrecer cobros, conserva ambas claves sin configurar y trata
configured:false como integración deshabilitada. Fuentes:
servicio FastAPI,
servicio NestJS
y sus validaciones de configuración enlazadas anteriormente.