CodeGym /Cursos /ChatGPT Apps /Errores típicos de despliegue y estrategia de depuración

Errores típicos de despliegue y estrategia de depuración

ChatGPT Apps
Nivel 7 , Lección 4
Disponible

1. Anatomía del despliegue: dónde puede romperse

Conviene ver primero toda la cadena. El despliegue de ChatGPT App en tu arquitectura se puede desplegar mentalmente en esta línea:

flowchart TD
  A[Tu portátil
git commit] --> B[Repositorio Git
GitHub/GitLab] B --> C[Vercel Build
npm run build] C --> D[Vercel Deploy
Preview/Prod] D --> E[Punto final HTTP
/mcp, /api/...] E --> F[ChatGPT / Dev Mode
llamadas de herramientas, widgets]

El fallo puede aparecer en cualquiera de estos pasos, pero los síntomas en ChatGPT se ven más o menos iguales: "Error talking to app", "Network error" o simplemente silencio. Tu tarea no es disparar a ciegas, sino entender primero: ¿se cayó en la fase de build, en tiempo de ejecución o ChatGPT está apuntando a otro sitio?

Es útil dividir los problemas en tres grandes categorías:

  • Errores de build: Vercel no pudo compilar el proyecto en absoluto. Producción no se actualizó — eso es «bueno», pero verás la build en rojo.
  • Errores en runtime: la build pasó, pero las peticiones devuelven 500/502, timeouts o comportamientos extraños.
  • Config drift (deriva de configuración): en local todo bien, en Vercel todo parece bien por logs, pero ChatGPT usa una URL antigua, trabaja con un manifiesto viejo o con variables env vacías.

Recorreremos estas tres capas y, en paralelo, construiremos una estrategia general de depuración.

2. Errores de build: cuando el proyecto no se compila

Este es el primer tipo de problemas de la introducción — errores de build: el proyecto no se compila en absoluto porque Vercel no puede construir tu proyecto Next.js.

Node y Next.js: otro entorno, otros requisitos

En local puedes (por desgracia) vivir con un Node obsoleto, mientras que Vercel intentará compilar tu proyecto Next.js 16 con una versión de Node soportada (mínimo 18.18.0). Si en package.json indicas explícitamente una versión incompatible, la build puede fallar en producción aunque tu servidor de desarrollo estuviera funcionando.

Una forma sencilla de protegerte es especificar en package.json la sección "engines":

{
  "engines": {
    "node": ">=18.18.0"
  }
}

Así, tanto en local como en CI/en Vercel verás con antelación que tu Node es demasiado antiguo.

«¡A mí me funciona!» y dependencias olvidadas

Clásico: instalaste una librería con npm install some-lib, pero no hiciste commit del package-lock.json actualizado o incluso tienes parte de las dependencias instaladas globalmente. En Vercel la app se compila «desde cero», ejecuta npm install basándose en el manifiesto, y tu querida some-lib no está — obtenemos un error de build.

Esto se arregla con disciplina estricta:

  • cualquier dependencia nueva se añade y se hace commit de inmediato;
  • antes de hacer push a main/production ejecutas npm run build en local. Si la build local falla, en Vercel será peor.

Sistema de archivos con distinción de mayúsculas y minúsculas

En local, muchos trabajan en macOS o Windows, donde el sistema de archivos por defecto no distingue mayúsculas/minúsculas en el nombre del fichero. En Vercel la build se ejecuta en un entorno Linux, allí Widget.tsx y widget.tsx son archivos distintos.

Bug típico:

// Import en el código
import { AppWidget } from "@/components/Widget";

// Pero en el repositorio el archivo es components/widget.tsx

En tu equipo todo funciona; en Vercel — error de módulo «Cannot find module '@/components/Widget'». Se arregla poniendo orden en los nombres y cuidando el uso del caso.

Variables de entorno (env) en la fase de build

Otra fuente de sorpresas — uso de process.env.* en código que se ejecuta durante la build (por ejemplo, en next.config.mjs o en módulos importados durante el build). Si en local cargaste .env.local, pero en Vercel olvidaste definir esas variables para el entorno de build, la build o bien fallará, o — peor — pasará con undefined y «horneará» valores no válidos en el bundle.

Para ChatGPT App esto es especialmente crítico si, por ejemplo, formas el baseURL para el endpoint MCP o la URL de APIs externas directamente en la fase de build.

Buena práctica — validar explícitamente las variables env críticas antes incluso de arrancar la aplicación (de esto hablaremos en una sección aparte), para que la build falle de forma clara y predecible.

3. Errores en runtime: cuando todo compila, pero no funciona

Pasamos ahora a la segunda capa de la introducción — errores en runtime: la build pasó, pero al ejecutar todo se rompe.

La build pasó, Vercel mostró alegremente un despliegue en verde, cambiaste ChatGPT App a la URL de producción — y obtuviste en el chat "Error talking to app". Entonces, los problemas han pasado al nivel de ejecución.

Env variables nulas o vacías

Con mucha frecuencia un incidente en producción en el mundo de ChatGPT App empieza con la palabra undefined. En local tienes un pulcro .env.local con OPENAI_API_KEY, MCP_BASE_URL y demás, pero en Vercel olvidaste definir estas variables o confundiste los nombres.

Por ejemplo, lees:

const apiKey = process.env.OPENAI_API_KEY;

pero en Vercel creaste OPENAI_APIKEY o OPENAI_API_KEY_PROD. Como resultado, en la primera llamada a una herramienta MCP tu route handler cae con un error de autenticación.

Mucho mejor cuando la aplicación cae enseguida y de forma comprensible. Un patrón útil — un módulo separado en tu proyecto Next.js que valide las variables env al importarse:

// app/lib/env.ts
const required = ["OPENAI_API_KEY", "MCP_BASE_URL"] as const;

type RequiredKey = (typeof required)[number];

function getEnv(key: RequiredKey): string {
  const value = process.env[key];
  if (!value) {
    throw new Error(`Missing required env var: ${key}`);
  }
  return value;
}

export const env = {
  OPENAI_API_KEY: getEnv("OPENAI_API_KEY"),
  MCP_BASE_URL: getEnv("MCP_BASE_URL"),
};

Ahora, si olvidaste configurar las variables en Vercel, Next.js fallará en cuanto importes env, y en los logs habrá un mensaje claro "Missing required env var: ...".

Es importante recordar que en Vercel los cambios en las variables de entorno no se aplican automáticamente. Tras cambiar valores hay que hacer un nuevo despliegue (redeploy), si no el runtime seguirá con los valores antiguos.

Errores en los route handlers y en el endpoint MCP

En la plantilla oficial de ChatGPT App el servidor MCP suele estar implementado como app/mcp/route.ts. Dentro tienes código que parsea la solicitud JSON‑RPC, la enruta a la herramienta y devuelve la respuesta. Si en algún punto de la cadena ocurre un throw sin manejo — el usuario en ChatGPT recibirá un 500.

Conviene envolver siempre el nivel superior del handler MCP en try/catch, loggear el error y devolver una respuesta estructurada:

// app/mcp/route.ts
import { NextRequest, NextResponse } from "next/server";

export const dynamic = "force-dynamic";
export const maxDuration = 30; // segundos

export async function POST(req: NextRequest) {
  try {
    const body = await req.json();
    // aquí se procesa la solicitud MCP
    const result = await handleMcpRequest(body);
    return NextResponse.json(result);
  } catch (error) {
    console.error("MCP route error", error);
    return NextResponse.json(
      { error: "Internal MCP error" },
      { status: 500 }
    );
  }
}

Un par de detalles:

  • dynamic = "force-dynamic" ayuda a evitar la generación estática inesperada y el caché para rutas MCP en Next.js 16.
  • maxDuration = 30 indica explícitamente a Vercel que el route handler puede ejecutarse hasta 30 segundos, algo importante para peticiones LLM largas.

Tiempos de espera (timeouts) y «Network error» en ChatGPT

Vercel limita el tiempo de ejecución de las funciones serverless: en planes gratuitos suele ser alrededor de 10 segundos, en planes de pago puede ser mayor (hasta varios minutos). Si tu herramienta MCP hace una petición larga a una base de datos o a un API externo, puede no contestar a tiempo, y ChatGPT recibirá "Network error" o un stream interrumpido.

Si usas streaming (SSE) para resultados parciales, es especialmente importante enviar los primeros bytes de la respuesta antes de que expire el timeout. Entonces la transmisión puede durar más, pero la plataforma no considerará que la función «se colgó».

Truco pequeño: mide el tiempo de las llamadas a herramientas y regístralo junto con el nombre de la herramienta. Así verás en logs que, por ejemplo, search_flights toma de forma constante 12 segundos y se queda un poco fuera del límite.

export async function safeToolCall<TInput, TOutput>(
  name: string,
  handler: (input: TInput) => Promise<TOutput>,
  input: TInput
): Promise<TOutput> {
  const started = Date.now();
  try {
    const result = await handler(input);
    console.log("[tool] ok", name, { ms: Date.now() - started });
    return result;
  } catch (error) {
    console.error("[tool] fail", name, {
      ms: Date.now() - started,
      error,
    });
    throw error;
  }
}

Luego, en lugar de handler(args) llamas a safeToolCall("search_flights", handler, args).

Red y servicios externos

A veces todo se debe a un simple https:// en lugar de http:// o a un baseURL obsoleto. Especialmente si primero probaste en tu máquina local con una URL y en producción ya tienes otro dominio u otro puerto.

Es útil extraer las URL base a la configuración (dependiente del entorno) y no coserlas directamente en el código de la herramienta. Así, al cambiar de entorno modificas una sola env y no tienes que recordar en qué cinco sitios del código tenías http://localhost:3001.

4. Configuración y deriva entre entornos

Y, por último, el tercer tipo de nuestra esquema — la deriva de configuración entre entornos.

Incluso si la build pasó y el runtime parece sano por logs, ChatGPT puede comportarse «como si estuviera funcionando otra versión de la aplicación». Es justo el caso en que el problema no es tanto de código, sino de configuración y coherencia entre entornos.

Dev Mode frente a producción

En Dev Mode, ChatGPT apunta al Connector URL que indicaste manualmente: normalmente es una URL de túnel (https://myapp-dev.ngrok-free.app/mcp o algo similar) o una URL de staging en Vercel. En producción (a través de Store o la configuración de la organización) la App debe apuntar a un endpoint de producción estable, por ejemplo https://myapp.vercel.app/mcp.

El error que casi todo el mundo comete: desplegaste en Vercel, pero en la configuración de ChatGPT App sigue la URL de túnel antigua. El servidor local está apagado, el túnel murió hace rato, y ChatGPT llama allí y recibe un 502. En la interfaz se ve como "Error talking to app", y el estudiante empieza a arreglar código MCP que en realidad ni se ejecuta.

Se arregla con disciplina: después de cualquier cambio de entorno (túnel → staging, staging → prod) verifica qué URL está puesta en Dev Mode y en la configuración de producción de la App.

Manifiesto antiguo y caché de ChatGPT

ChatGPT cacheará información sobre tu App: lista de herramientas, sus descripciones, metadatos. Por eso la situación «he cambiado el esquema de la herramienta, pero el modelo sigue pensando que el argumento se llama como antes» — es real.

Ante cambios serios de herramientas es útil:

  • asegurarte de que realmente desplegaste la nueva versión (mirar el hash del commit en los logs, mostrarlo en el log de arranque);
  • recrear o volver a conectar la App en Dev Mode para forzar a la plataforma a releer el manifiesto;
  • durante la depuración, trabajar con MCP Inspector, donde verás con certeza la lista y los esquemas actuales de herramientas.

Config de env: dev/staging/prod

Ya hablamos de cómo las variables env pueden romper la build y el runtime. Aquí — una vista desde arriba a dev/staging/prod y la coherencia de valores entre ellos.

Dolor habitual: tu .env.local es perfecto, y en los entornos de Vercel — un zoológico. En consecuencia:

  • en local tienes una API key y una URL de servicio externo;
  • en staging — valores completamente distintos;
  • en prod — la mitad de las variables ni están definidas.

Ayuda mucho un archivo de texto simple docs/env.md en el repositorio, donde enumeras: qué variables se necesitan, en qué entornos son obligatorias y ejemplos de valores. Puede parecer burocracia, pero en un incidente esa lista ahorra horas.

5. Cómo se ven los errores del lado de ChatGPT

Veamos ahora la situación con los ojos del usuario de ChatGPT. Él solo ve la interfaz y no sabe nada de Vercel, Node ni MCP. Y tú, por desgracia, de momento tampoco sabes qué se rompió.

Síntomas típicos en ChatGPT:

  • mensaje "Error talking to [App Name]" justo después de intentar usarlo;
  • spinner infinito sin error visible;
  • texto en rojo "I encountered an error while running the tool";
  • el widget no aparece o aparece vacío.

Cada uno de estos síntomas suele corresponder a un nivel de fallo concreto:

  • si la App no está disponible (URL incorrecta, túnel caído, error SSL), ChatGPT no puede contactar con tu endpoint MCP — mira la disponibilidad del dominio en el navegador y los logs de Vercel con códigos 4xx/5xx;
  • si MCP responde con un JSON‑RPC válido con el campo error, ChatGPT indicará que la herramienta devolvió un error — ya es un tema de lógica de negocio o validación de argumentos;
  • si MCP responde con éxito, pero la respuesta contiene HTML del widget roto o un error de JS, en la consola del widget (DevTools → iframe del widget) se verá qué ha fallado.

Por eso es buena costumbre: en cuanto veas un comportamiento extraño en el chat, toma el timestamp (al menos al minuto) y ve a los logs de Vercel a buscar las peticiones de ese momento.

6. Estrategia de depuración: no entrar en pánico, actuar

Ahora juntaremos todo lo dicho en un pequeño «playbook» — un guion de actuación cuando algo sale mal. La meta — cambiar la carrera en círculos por un algoritmo tranquilo.

Paso 1: identificar el tipo de problema

Si la build en Vercel está en rojo — buena noticia: el error se atrapó antes de llegar a producción. Abre los logs de build, mira el primer error real (no 200 líneas de warnings) y reprodúcelo en local con npm run build.

Si la build está en verde, y ChatGPT se queja — es runtime o configuración. Comprueba:

  • si la URL de producción de tu App es accesible desde el navegador (https://myapp.vercel.app/mcp devuelve algo);
  • si el endpoint MCP devuelve 200/500 o ni siquiera resuelve;
  • si la URL en la configuración de la App coincide con la que acabas de comprobar.

Paso 2: leer logs, no mentes

Siguiente parada — los logs de Vercel: logs del servidor para el despliegue y entorno (Preview/Production) correctos.

Busca:

  • errores Error: Missing required env var ... — entonces el problema es de configuración;
  • stack trace del handler MCP — entonces está fallando la lógica de negocio o el parseo de datos de entrada;
  • mensajes sobre timeouts o superación de la duración de la función.

En paralelo, no olvides MCP Inspector. Si te conectas al mismo endpoint MCP a través del inspector y llamas a las herramientas manualmente, entenderás rápido si el problema está en MCP en sí o en el enlace ChatGPT ↔ MCP.

Paso 3: ¿rollback rápido o hotfix?

Si ves que el despliegue de producción está claramente roto (por ejemplo, la ruta MCP lanza el mismo error en cada petición), y el despliegue anterior estaba sano, la decisión correcta es volver atrás. Vercel permite cambiar rápidamente al despliegue exitoso anterior sin recompilar — es básicamente cambiar la versión activa.

Esto es mejor que intentar arreglar producción «en caliente», especialmente si no comprendes del todo la causa del incidente.

Cuando la situación esté estabilizada, analizas con calma la causa, escribes tests, corriges en código y entonces publicas la siguiente versión.

Paso 4: consolidar el conocimiento en la documentación

Cualquier incidente serio — motivo para actualizar el README interno:

  • añadir a la lista una variable env obligatoria sin la cual todo cae;
  • anotar qué caso concreto llevó al error (por ejemplo, «import con mayúsculas/minúsculas incorrectas en los nombres de archivos»);
  • describir el algoritmo breve de acciones que ayudó a arreglar todo rápido.

Parece aburrido, pero dentro de un par de meses te lo agradecerás.

7. Pequeños trucos prácticos en el código

Tomemos ahora algunos pasos de nuestro playbook y fijémoslos con pequeños trucos de código en nuestra aplicación de ejemplo (ChatGPT App).

Módulo de configuración unificado

Ya escribimos un validador simple de variables env. Se puede ampliar para distinguir entornos:

// app/lib/config.ts
type NodeEnv = "development" | "test" | "production";

const nodeEnv = (process.env.NODE_ENV || "development") as NodeEnv;

const requiredBase = ["OPENAI_API_KEY"] as const;
const requiredProd = ["MCP_BASE_URL"] as const;

function ensure(keys: readonly string[]) {
  for (const key of keys) {
    if (!process.env[key]) {
      throw new Error(`Missing env var ${key} for NODE_ENV=${nodeEnv}`);
    }
  }
}

ensure(requiredBase);
if (nodeEnv === "production") {
  ensure(requiredProd);
}

export const config = {
  nodeEnv,
  openaiApiKey: process.env.OPENAI_API_KEY!,
  mcpBaseUrl: process.env.MCP_BASE_URL ?? "http://localhost:3000/mcp",
};

Un módulo así te avisará de inmediato si producción arranca sin la variable necesaria.

Registro (logging) de solicitudes MCP entrantes

Un wrapper simple pero muy útil para el handler MCP:

// app/lib/mcp-logger.ts
export function logMcpRequest(body: unknown) {
  console.log("[mcp] request", {
    time: new Date().toISOString(),
    // no registramos datos sensibles
    keys: typeof body === "object" && body !== null
      ? Object.keys(body as Record<string, unknown>)
      : typeof body,
  });
}

Y lo usamos en app/mcp/route.ts:

import { logMcpRequest } from "@/app/lib/mcp-logger";

export async function POST(req: NextRequest) {
  try {
    const body = await req.json();
    logMcpRequest(body);
    const result = await handleMcpRequest(body);
    return NextResponse.json(result);
  } catch (error) {
    console.error("MCP route error", error);
    return NextResponse.json({ error: "Internal error" }, { status: 500 });
  }
}

En los logs verás qué llega desde ChatGPT: al menos por las claves ("jsonrpc", "method", "params"), y te será más fácil entender qué llamada concreta está fallando.

Comprobación sencilla de disponibilidad del endpoint MCP

A veces es útil tener un pequeño route handler tipo «healthcheck» para el servidor MCP, que ChatGPT no llama directamente, pero que puedes abrir rápido en el navegador para saber si el servidor está vivo y ve sus variables env:

// app/api/health/route.ts
import { NextResponse } from "next/server";
import { config } from "@/app/lib/config";

export async function GET() {
  return NextResponse.json({
    status: "ok",
    env: config.nodeEnv,
    hasOpenAiKey: !!config.openaiApiKey,
  });
}

Si https://myapp.vercel.app/api/health responde status: "ok", entonces al menos el pipeline básico hasta tu código Node está vivo.

8. Errores típicos al desplegar y depurar

Error n.º 1: Despliegue sin npm run build local.
Cuando el desarrollador nunca ejecuta la build en local, se entera de la versión incompatible de Node, del problema con rutas o del error de TS solo en Vercel. Esto alarga el ciclo «rompí → arreglé», porque cada experimento es un despliegue nuevo. El hábito de ejecutar npm run build antes de hacer push a main ahorra mucho tiempo (véase también la sección 2 y el paso 6.1 sobre el npm run build local).

Error n.º 2: Los secretos solo están en .env.local.
El proyecto funciona perfectamente en la máquina del autor, pero en producción cae porque process.env.OPENAI_API_KEY === undefined. La causa es banal: olvidaron añadir las variables env en la configuración de Vercel (y a veces incluso las nombraron distinto). Con frecuencia se olvida la separación Development/Preview/Production y sorprende que staging y prod se comporten diferente (más detalles — secciones 3.1, 4.3 y 7.1).

Error n.º 3: Usar NEXT_PUBLIC_* para secretos.
En Next.js todas las variables con el prefijo NEXT_PUBLIC_ van al bundle del navegador. Si por despiste llamaste a la API key NEXT_PUBLIC_OPENAI_API_KEY, se irá al navegador del usuario y se puede extraer desde las DevTools. No se debe hacer. Solo deben ser públicas las variables seguras (por ejemplo, identificadores de feature flags, pero no tokens).

Error n.º 4: Ignorar los logs de Vercel e intentar «arreglarlo con ChatGPT».
A veces el desarrollador ve en el chat "Error talking to app" y se pasa horas cambiando prompts, descripciones de herramientas, tocando cosas en Dev Mode, pero ni una vez mira los logs del serverless. Y allí suele haber un error bastante claro: "Missing env var", "Cannot find module" o el stack trace de una herramienta concreta. Un buen ingeniero primero mira los logs y luego discute con el modelo.

Error n.º 5: Confundir Dev Mode con la App de producción.
Tras el primer despliegue exitoso en Vercel es fácil olvidar que Dev Mode puede seguir apuntando a un túnel antiguo o a una URL de preview. Como resultado, crees que pruebas la versión de producción, pero en realidad hablas con una rama local que ya deberías haber eliminado. O al revés: crees que pruebas cambios de borrador y ChatGPT llama al endpoint en producción. Hay que revisar con regularidad qué URL está indicada en la configuración de la App y en Dev Mode (véase también la sección 4.1 sobre Dev Mode y producción).

Error n.º 6: Esperar que el cambio de una variable env en Vercel funcione «al vuelo».
Algunos estudiantes cambian valores de variables en el panel de Vercel y corren a ChatGPT a comprobar el resultado. Pero el runtime sigue usando los valores antiguos porque no hubo redeploy. Cualquier cambio de variables env requiere un nuevo despliegue; si no, la función no verá la actualización (más detalles — sección 3.1).

Error n.º 7: No tener una estrategia simple de rollback.
En un incidente, la tentación de «hacer push rápido del fix» directamente a main es grande. Pero eso añade otro despliegue potencialmente roto, mientras los usuarios siguen sufriendo. Más prudente es tener el hábito de, ante un error serio, volver inmediatamente al despliegue exitoso anterior, arreglar el problema en una rama aparte y solo después publicar la nueva versión. Vercel ofrece una interfaz cómoda para ello, sería un pecado no usarla.

1
Cuestionario/control
Depuración y despliegue, nivel 7, lección 4
No disponible
Depuración y despliegue
Entornos, depuración y despliegue (Vercel + túnel)
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION