El logger que se cayó tratando de reportar su propio crash
Cerré el trabajo de i18n de la portada con una nota en la base de conocimiento que básicamente decía “npm run dev está roto acá, usar npm run preview en su lugar.” Eso me molestó. Había documentado un síntoma y un workaround, no una causa. Así que abrí un follow-up y de verdad me puse a leer el código.
El error era process is not defined, lanzado desde dentro del propio logger de Astro mientras el logger intentaba reportar un error completamente distinto. Un crash reportando un crash. Y pasaba en todas las rutas, no solo en la página que acababa de escribir, lo cual fue la señal de que esto no tenía nada que ver con el trabajo de traducción al español.
Resulta que Astro está vigilando si hay agentes de código
Astro 7 incluye un paquete llamado am-i-vibing que detecta si se está ejecutando dentro de un agente de código con IA. Vale la pena leerlo dos veces, la herramienta de build comprueba si lo que la está invocando es un agente. Y en esta configuración, casi siempre lo es: un agente maneja la mayoría de estas sesiones de desarrollo.
const agentDetected = !process.env.ASTRO_DEV_BACKGROUND && isRunByAgent();
if (agentDetected) {
flags.json = true;
}
...
if (flags.background || agentDetected) {
await background({ flags, logger });
}
Cuando detecta un agente, activa automáticamente el logging estructurado en JSON y convierte el servidor de desarrollo en un daemon en segundo plano, lo cual explica el extraño mensaje “Stop: astro dev stop / Status: astro dev status / Logs: astro dev logs” que venía viendo sin cuestionarlo. Es una función bien pensada: los agentes no quieren un proceso bloqueante en primer plano, y los logs estructurados son más fáciles de parsear que la salida de terminal con colores ANSI. Astro construyó esto justo para el flujo de trabajo que uso.
El bug escondido dentro de la función
La función write del logger JSON hace esto, sin ninguna protección:
write(event) {
let dest = process.stderr;
...
dest.write(JSON.stringify({ ... }));
}
Eso está bien en un proceso normal de Node. Pero el modo dev de @astrojs/cloudflare no renderiza páginas en Node, levanta un sandbox real de workerd, el runtime real de Cloudflare Workers, para que lo que se ve en local se parezca lo más posible a producción. Ese sandbox no tiene el global process. No es Node. Entonces, en el instante en que algo dentro de ese sandbox necesitó registrar un error, el logger JSON buscó process.stderr, no encontró nada, y lanzó una excepción, y esa falla secundaria fue lo único que llegó a mi navegador.
Todavía no sé cuál era el error original. Sí sé cuál fue su reemplazo, y eso fue suficiente para resolverlo bien en vez de adivinar.
La solución
Poner ASTRO_DEV_BACKGROUND=1 antes de astro dev anula por completo la detección de agente, sin logger JSON, sin daemon, solo el logger normal de Node con formato legible, que funciona bien porque solo corre en el proceso padre del CLI, nunca dentro del sandbox de workerd. Una línea en package.json:
- "dev": "astro dev",
+ "dev": "ASTRO_DEV_BACKGROUND=1 astro dev",
Lo confirmé bombardeando /, /blog/ y /es/ repetidamente, 200 limpios cada vez, cuando antes de la solución cada ruta devolvía 500 de forma consistente por el resto de la vida de ese servidor.
Lección
“Funciona si uso el otro comando” es un workaround. Tomó tal vez quince minutos extra leer de verdad astro/dist/cli/dev/index.js y logger/impls/json.js en vez de quedarme en la nota que ya había escrito a medias, y esa es la diferencia entre “acá hay algo para probar” y “acá está exactamente qué está mal y por qué.” La segunda es la que sigue siendo cierta la próxima vez que Astro lance una versión menor.
Lecturas relacionadas
Mi corrección fue correcta todo el tiempo, mi servidor de desarrollo simplemente se negaba a decirlo
Vite no vigila node_modules, un servidor detenido que en realidad no lo estaba, y el respaldo de puerto que me hizo probar el código de la semana pasada mientras leía el código fuente de esta semana.
Cerrar el círculo de la sección Open Source, y el 404 que no podía correr código de servidor
Localizar una página de error sin ningún servidor involucrado, una verificación de ruta que se habría roto en /estimates, e infraestructura publicada a sabiendas de que todavía no hace nada.
El formateador que nunca revisó su propia carpeta de scripts
Un gate de despliegue que corrió, pasó, y nunca miró el directorio que contiene el script que se ejecuta antes de que empiece el build.