Cuándo
El corpus de Ayuda en español (wiki-es/) se congeló el 2026-06-14 con 83 páginas, sincronizado 1:1 contra el corpus canónico inglés (wiki/) de ese momento. Dos artículos nuevos (“The Device page” y “Create a Row of racks”) se añadieron al corpus inglés después de esa fecha, sin gemelo español. Desde entonces y hasta el arreglo el 2026-08-23 (task #254, ronda 23-08, PR #419), cualquier usuario con la sesión en español que abriera esos dos artículos veía el fallo. Duración estimada: ~9 semanas, sin que ninguna alarma ni log lo señalara.
Síntomas visibles
El panel de Ayuda, con la interfaz en español, mostraba como contenido del artículo el volcado crudo {"error":"File not found: …"} en lugar del texto esperado. No había ningún error en los logs de aplicación (la petición HTTP al workspace devolvía 200), ninguna alarma de HighErrorRate se disparaba, y el fallo solo era visible para quien abriera esos dos artículos concretos en español.
Causa raíz
Dos fallos independientes que se combinaban:
_apply_language(data, lang)(introducida en sesión 137, 2026-06-14) reescribía todas las rutaswiki/→wiki-es/paralang=es, sin comprobar que existiera el gemelo español. El comentario del código afirmaba “la simetría es total (82 = 82 páginas), así que el rewrite nunca da 404” — cierto en el momento de escribirlo, falso en cuanto el corpus EN creció sin que el ES lo acompañara._mcp_call(tool_name, arguments)no distinguía contenido válido de un payload de error: el workspace MCP responde con HTTP 200 y cuerpo{"error": "..."}cuando el artículo no existe en esa ruta —resp.raise_for_status()no lo detecta porque el código de estado es 200. Ese JSON viajaba íntegro como si fuera el texto del artículo y se pintaba tal cual.
Ninguno de los dos fallos por separado bastaba para el síntoma: el primero servía una ruta wiki-es/ inexistente, y el segundo era el que convertía el 404 semántico del workspace en contenido aparentemente legítimo.
Fix aplicado
Commit 3133a0e9a613c9743d14444b248ea6db61ef676d (PR #419, v1.82.1):
_mcp_callahora detecta cuando el cuerpo es un JSON con clave"error"y lanzaRuntimeError— se convierte en el 502 honesto que cada caller del Help Widget ya sabía manejar (Regla 15 — HTTP 200 ≠ éxito — aplicada en el punto exacto donde dolía; blinda el puente MCP entero, no solo el camino de artículos)._apply_languagesolo reescribe la ruta de un artículo cuyo título está presente en el mapa de traducción (wiki-es/titles.json) — es decir, que tiene gemelo español confirmado. Los artículos sin traducir conservan su ruta inglesa y se sirven en inglés (degradación elegante) en lugar de una ruta española rota.- +3 tests en
tests/api/test_help.py(test_apply_language_es_untranslated_keeps_en_path,test_mcp_call_raises_on_error_payload,test_mcp_call_passes_markdown_and_legit_json).
De regalo, en el mismo commit: las categorías “ups”/“wireless”/“settings” del panel de Ayuda (que caían al final por no estar en el array de orden de alpine-components.js) pasan a tener posición fija, y el tooltip del botón Help —que estaba en español en 5 plantillas de un producto en inglés (Regla 1)— se unifica al msgid canónico 'Help & AI assistant'.
Lecciones
- Un comentario que afirma una invariante (“simetría total, nunca da 404”) sin nada que la verifique en runtime se pudre en silencio en cuanto el dato de origen cambia — el corpus EN creció y nadie recordó actualizar el supuesto.
- Regla 15 (“HTTP 200 ≠ éxito”) no es solo para APIs externas: aplica igual a la integración interna equipo-a-equipo entre CreaRack-Pro y el workspace MCP, donde un 200 con
{"error": ...}es un patrón real del propio backend interno. - Un fallo sin log, sin alarma y limitado a 2 artículos de N en un idioma concreto es exactamente el tipo de bug que sobrevive semanas: no dispara ningún mecanismo de detección existente.
Preventivos futuros
Los 3 tests nuevos cubren como regresión los dos escenarios exactos de este incidente (artículo sin gemelo ES, payload de error del MCP). Queda como mejora futura no implementada en este fix: un chequeo de contrato en CI que compare el catálogo wiki/ vs wiki-es/ y avise de asimetrías antes de desplegar, en vez de depender de que el código de aplicación degrade con gracia.
Véase también
- [[entity—core—service—api-help]]
- [[entity—core—endpoint—help-ask]]
- [[entity—core—endpoint—api-help-wiki]]
- [[entity—core—component—help-widget]]
- [[feature—ux—help-widget]]
- [[workspace—producto—sistema-ayuda-ingles]]