Saltar al contenido principal

Solución de problemas

Empieza por la capa que falla: navegador, frontend, backend, Ollama, plugin de proveedor o red del despliegue.

Comprobaciones rápidas

# App branch and local changes
git status

# Backend process liveness
curl http://localhost:3001/health/live

# Backend dependency readiness (SQLite, schema, and writable data storage)
curl http://localhost:3001/health/ready

# Ollama health
curl http://localhost:11434/api/tags

# Installed Ollama models
ollama list

En desarrollo, el frontend suele estar en http://localhost:5173 y el backend en http://localhost:3001. El flujo empaquetado npx libre-webui sirve la aplicación en http://localhost:8080.

Libre WebUI no se inicia

Comprueba Node y las dependencias

node --version
npm install
npm run dev

Se requiere Node.js 22.22 o posterior.

Puerto en uso

lsof -i :3001
lsof -i :5173
lsof -i :8080

Detén el proceso anterior o configura otro puerto.

El backend no puede escribir datos

El backend almacena los datos en DATA_DIR si está definida, si no en backend/data. Los inicios desde fuente resuelven un DATA_DIR relativo desde el directorio del backend, no la shell. Por ello DATA_DIR=./data selecciona backend/data, mientras el valor histórico DATA_DIR=./backend/data selecciona backend/backend/data. Comprueba que se pueda escribir. Sin DATA_DIR, Libre conserva el directorio histórico si es el único almacén. Si ambos contienen datos, detén Libre, copia ambos y elige o migra deliberadamente; nunca combina ni copia bases divergentes.

Los endpoints distinguen un proceso vivo de una aplicación utilizable:

  • /health y /health/live devuelven 200 mientras el backend sirva HTTP. Los proveedores opcionales no afectan.
  • /health/ready devuelve 503 si una base, esquema, almacenamiento o dependencia obligatoria no está disponible. No espera a proveedores opcionales y su respuesta pública omite errores y detalles.
  • /health/deep ejecuta comprobaciones de integridad y claves foráneas de SQLite en un trabajador acotado y agrupa sondeos opcionales como Ollama. Su caída es una advertencia, no vuelve no preparado lo obligatorio. Exige un Bearer de administrador actual y no sirve para sondeos frecuentes.
curl -H "Authorization: Bearer $LIBRE_ADMIN_TOKEN" \
http://localhost:3001/health/deep

El navegador no llega al backend

En desarrollo, el frontend usa VITE_API_BASE_URL si está definida y de lo contrario el backend predeterminado.

Ejemplo de .env del frontend:

VITE_API_BASE_URL=http://localhost:3001/api
VITE_WS_BASE_URL=ws://localhost:3001

VITE_WS_BASE_URL es opcional, pero al definirla es la base de los sockets de Chat y terminal Work. Usa una URL absoluta ws: o wss:; admite prefijos como wss://example.com/libre. No incluyas credenciales, consultas ni fragmentos. Reinicia o recompila tras cambiar variables Vite.

Ejemplo de .env del backend:

CORS_ORIGIN=http://localhost:5173,http://127.0.0.1:5173

Para teléfono, LAN o Tailscale, no apuntes el teléfono a localhost; utiliza la IP LAN o Tailscale del portátil y ejecuta el servidor enlazado al host:

npm run dev:host

Esto sirve el frontend en el puerto 8080 y reenvía el tráfico de API y WebSocket al backend local en el puerto 3001. Solo el puerto 8080 necesita ser accesible desde el otro dispositivo. Si VITE_API_BASE_URL o VITE_WS_BASE_URL está definida en frontend/.env, asegúrate de que esas URL sean accesibles desde el otro dispositivo, o elimínalas para usar el proxy del servidor de desarrollo.

Chat no transmite tras un proxy inverso

El síntoma habitual es que se envían mensajes pero no aparece respuesta y la consola muestra un fallo WebSocket. Confirma que el proxy admita actualizaciones y no cierre conexiones largas.

Cuando se configura alguno, las actualizaciones del navegador con Origin se comprueban contra CORS_ORIGIN y BASE_URL. Define al menos uno para un despliegue remoto; sin ambos el filtro sigue permisivo para desarrollo. Electron y otros clientes pueden omitir Origin, pero deben canjear Authorization por un ticket breve de un uso. Mantén el backend tras TLS y los mismos controles que la API HTTP.

Para un host público, permite ese origen en el servicio:

services:
libre-webui:
environment:
CORS_ORIGIN: https://chat.example.com
BASE_URL: https://chat.example.com

Los ejemplos de nginx y Caddy suponen que el proxy está en el host Docker, donde Compose publica Libre WebUI en 8080. Si se une a la red Compose, usa libre-webui:3001 como upstream.

nginx

nginx requiere reenviar expresamente las cabeceras. La espera larga mantiene abierto un chat inactivo mientras trabaja el modelo.

location /ws {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}

Recarga nginx tras validar con nginx -t.

Caddy

reverse_proxy de Caddy admite WebSockets directamente:

chat.example.com {
reverse_proxy 127.0.0.1:8080
}

Traefik

Traefik también gestiona las actualizaciones. Si su proveedor Docker comparte la red, bastan etiquetas normales:

labels:
- 'traefik.enable=true'
- 'traefik.http.routers.libre-webui.rule=Host(`chat.example.com`)'
- 'traefik.http.routers.libre-webui.entrypoints=websecure'
- 'traefik.http.routers.libre-webui.tls=true'
- 'traefik.http.services.libre-webui.loadbalancer.server.port=3001'

Si conecta y se corta, comprueba esperas de inactividad en proxies o equilibradores. Si Traefik impone el límite, ajusta transport.respondingTimeouts del punto de entrada.

Ollama no se detecta

Confirma que Ollama se ejecute

curl http://localhost:11434/api/tags

Configura una URL personalizada

.env del backend:

OLLAMA_BASE_URL=http://localhost:11434

Si Libre WebUI está en Docker y Ollama en el host, utiliza el archivo Compose externo o apunta OLLAMA_BASE_URL a una dirección del host accesible desde el contenedor.

Problemas al descargar modelos

Descarga primero desde el terminal

ollama pull gemma4:12b

Si falla, el problema está fuera de Libre WebUI.

Modelos en la nube

Usa el filtro de nube del gestor para Ollama Cloud. Libre WebUI normaliza los sufijos necesarios; no hace falta añadir :cloud manualmente a entradas compatibles.

Un usuario no puede descargar

Los administradores pueden impedir descargas a usuarios normales. Comprueba los ajustes si pueden navegar pero no instalar.

Chat es lento o falla

  • Usa un modelo más pequeño.
  • Comprueba los cargados con ollama ps.
  • Reduce el contexto.
  • Reduce los tokens máximos de respuestas largas.
  • Confirma que cabe en RAM/VRAM.
  • En plugins, verifica clave y cuota.

La generación de imágenes OpenAI no está disponible

  • Activa el proveedor incluido. Guarda una clave para el usuario o configura la reserva de confianza OPENAI_API_KEY.
  • Abre los ajustes de imágenes, actívalas y selecciona un modelo GPT Image anunciado.
  • Prefiere gpt-image-2. Los ID anteriores son solo para compatibilidad y están obsoletos.
  • Deja image_endpoint vacío salvo que operes uno compatible. Un endpoint /responses o /chat/completions no procesa Image API.
  • Si OpenAI rechaza con clave y cuota válidas, confirma que la organización pueda usar GPT Image.

La disponibilidad se evalúa con la credencial del usuario o la reserva incluida. Una clave de otra cuenta no expone modelos.

Problemas de endpoints de proveedores

Si un proveedor compatible recibe solicitudes en una ruta incorrecta, revisa Ajustes → Plugins:

  • Elige Chat Completions para /chat/completions o Responses para /responses.
  • Introduce la raíz, como https://provider.example/v1, como URL base.
  • Deja la ruta vacía para el valor del modo o introduce una ruta con barra inicial.
  • Un endpoint completo verdaderamente personalizado prevalece; bórralo para volver a Base URL y API Path. Los valores que solo igualan el antiguo predeterminado se ignoran tras actualizar. Un sufijo /chat/completions o /responses también determina el formato para impedir cargas erróneas.

El JSON importado admite formatos OpenAI Chat Completions, OpenAI Responses, Anthropic o Gemini. Un formato propietario de carga, streaming, herramientas o respuesta necesita un adaptador; cambiar solo el endpoint no lo traduce.

Las URL admiten HTTP o HTTPS. HTTP envía credenciales y tráfico sin cifrar, así que resérvalo para puertas autoalojadas fiables y prefiere HTTPS. Las URL base no pueden incluir consulta ni fragmento, y las rutas relativas no pueden contener traversal literal o recodificado, consultas ni fragmentos. Se rechaza codificación excesiva que no se estabilice.

La actualización sustituye sufijos conocidos, incluido /responses, por /models. Activación, actualización y anulaciones usan endpoint y clave del usuario. Guardar o borrar la clave y restablecer conexión también actualiza; los parámetros de generación no. Los ID se guardan por usuario y no reescriben JSON. Si la ruta derivada no funciona, configura model_map.

Las solicitudes no siguen redirecciones HTTP, incluido descubrimiento, Chat, Work, imágenes, embeddings y voz. Configura el destino final. Así Authorization no salta a un destino no validado.

Si Work indica que cambió el enrutamiento, inicia una ejecución nueva tras terminar el cambio. Se detiene antes de la siguiente solicitud para no repetir estado anterior a otro modo, endpoint o clave.

Las solicitudes salen del backend; localhost dentro de un contenedor es el contenedor, no el host. En Compose o Kubernetes utiliza DNS del servicio, como http://ai-gateway:8080/v1. Usa http://host.docker.internal:8080/v1 solo si existe. HTTP sigue sin cifrar.

Los modelos de imagen, anulaciones y claves también se resuelven para el usuario actual. Verifica la autenticación si parecen de otra cuenta.

También se aplican estas reglas:

  • Inicia sesión como administrador para cambiar rutas. Definiciones y conexiones son configuración de instancia; los usuarios guardan generación, credenciales y activación.
  • Con endpoint o api_url, introduce la URL completa de operación, por ejemplo https://provider.example/v1/chat/completions. Una raíz solo va en base_url, junto a api_mode y api_path opcional.
  • Se aceptan HTTP y HTTPS absolutas. Usa HTTP solo en red fiable porque claves, prompts y respuestas no están cifrados.
  • Una anulación vacía usa el manifiesto. Una explícita no segura se rechaza; Libre no vuelve silenciosamente.
  • Una clave de entorno solo se usa si una definición incluida no sombreada mantiene raíz, autenticación, endpoints y selectores y valores de enrutamiento de confianza. Las importadas, escribibles con ID incluido y rutas personalizadas exigen credencial de la misma cuenta. Libre informa no disponible y omite descubrimiento si solo hay clave de entorno.
  • Las definiciones personalizadas antiguas están en cuarentena por falta de procedencia. Reimporta como administrador y haz que cada usuario reactive. Editar JSON directamente vuelve a ponerlo en cuarentena; usa instalación o actualización.
  • Las credenciales se vinculan a ruta, autenticación, definición y fuente. Guárdalas otra vez tras cambiar. Una antigua sin vínculo solo migra en una ruta incluida exacta.
  • Los plugins importados pueden usar api_url; endpoint prevalece. Si la lista está en otro lugar, define models_endpoint completo; se valida y no redirige.
  • Activa tras guardar endpoint y credencial. La activación deriva /models y usa la credencial del usuario salvo models_endpoint. Guardar o restablecer también actualiza y espera antes de recargar. La activación es por cuenta.
  • En Ajustes → Plugins, usa Actualizar modelos. La tabla de lectura muestra ID configurados o descubiertos. Un fallo transitorio conserva el catálogo anterior o model_map; terminar no demuestra que el remoto esté sano.
  • El descubrimiento automático exige matriz data. Los catálogos son por usuario. Una activación normal conserva el anterior; cambiar conexión lo borra primero y un fallo usa model_map.
  • La disponibilidad de imágenes y claves también es por usuario; verifica quién está autenticado.
  • Si un usuario no administrador guardó enrutamiento antiguo, usa Restablecer. Se purga el valor ignorado y los modelos descubiertos para que no revivan tras cambiar rol.
  • Las solicitudes se originan en el backend; localhost en contenedor es el contenedor.
  • No se siguen redirecciones; configura la URL final.

Chat usa el proveedor equivocado o lo muestra no disponible

El mismo ID puede existir en Ollama y plugins. Las sesiones y preferencias actuales guardan proveedor e ID, por lo que son opciones independientes.

  • Si aparece no disponible, reactiva o reinstala ese plugin y confirma que aún anuncia el ID.
  • Si se eliminó, selecciona expresamente otro. Libre no redirige una selección exacta a un homónimo.
  • Sesiones antiguas pueden no tener metadatos. Mantienen enrutamiento por nombre porque no puede inferirse el origen y aparecen como «proveedor no registrado». Vuelve a seleccionar para fijarlo.
  • Las personas siguen etiquetadas persona:<id>. Las nuevas registran Ollama como respaldo; las históricas siguen compatibles.

Problemas de Work

Work no aparece o el entorno no está disponible

Work requiere una cuenta autenticada con acceso —administrador o usuario activo tras abrirlo a todos— y un entorno accesible al backend:

docker info
docker version

Para Docker, confirma que se ejecute y que el usuario del sistema pueda invocar WORK_DOCKER_COMMAND. Instalar mediante npx no instala Docker. Si falta, el resto de la aplicación sigue disponible y Libre no ejecuta comandos del modelo en el host.

Compose activa Work montando el socket. En Kubernetes activa Pod/PVC con work.enabled=true; no montes socket de nodo. Si Compose sigue mostrando Runtime unavailable, la página indica el caso:

MensajeCausa y solución
The "docker" CLI is not installed…Imagen personalizada sin docker-cli. Usa la oficial o apunta WORK_DOCKER_COMMAND a un CLI.
No Docker daemon is reachable…Se quitó el montaje o se detuvo el daemon. Restáuralo e inicia Docker.
The Docker socket is mounted but…cannot openEl grupo difiere del contenedor. Define DOCKER_GID en .env y recrea el contenedor.
La pantalla o el audio de Work se cierran con el WebSocket 1006 y registran screen is unreachableEl backend en contenedor está llamando a su propio loopback. En Docker Desktop usa el valor incluido WORK_DOCKER_PUBLISHED_HOST=host.docker.internal; en Docker Engine nativo define además WORK_PREVIEW_BIND con la puerta de enlace no pública del puente de Docker y recrea Libre WebUI.

Lee el grupo desde un contenedor porque macOS muestra otro:

echo "DOCKER_GID=$(docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
alpine stat -c '%g' /var/run/docker.sock)" >> .env
docker compose up -d --force-recreate

El socket concede control equivalente a root; consulta Work: espacios de trabajo aislados.

El modelo no admite herramientas

Work requiere un modelo de chat con herramientas. En Ollama, elige uno cuyas capacidades incluyan tools. Para plugins:

  • Confirma que el plugin chat o completion esté activo.
  • Confirma el modelo en su lista.
  • Confirma una clave para el administrador actual.
  • Confirma herramientas en ese modelo exacto.

Libre no redirige una ejecución fallida.

Una solicitud devuelve HTTP 429

La instancia alcanzó un límite de tareas o entornos activos. De forma predeterminada permite dos tareas con contenedor en la instancia y una por usuario. Una vista previa también ocupa capacidad. Espera, detén una vista o revisa WORK_MAX_ACTIVE_RUNTIMES_* y WORK_MAX_TASKS_*.

Falla la instalación de paquetes o la red

Las tareas usan red puente Docker para descargar paquetes e iniciar vistas. Comprueba DNS, proxy, registro y salida en Actividad. Libre no monta claves SSH, credenciales cloud, perfiles de navegador ni socket Docker dentro de la tarea.

Una vista previa no se inicia

  • Asegúrate de que el servidor se vincule a 0.0.0.0 en WORK_PREVIEW_PORT (4173 predeterminado).
  • Deja el comando opcional vacío para detectar un script dev de package.json o index.html, incluso una aplicación anidada única.
  • Si hay varias o ninguna entrada, introduce el comando de desarrollo. Empieza en /workspace; usa cd <app-directory> && ... para una anidada.
  • Amplía los detalles del error.
  • Detén una vista existente antes de otro comando que necesite el contenedor.

Las URL usan un puerto dinámico de bucle invertido. Navegador y backend deben estar en el mismo equipo. Un navegador conectado a un backend remoto no llega a su bucle y una página HTTPS puede bloquear una vista HTTP como contenido mixto.

No se puede abrir o guardar un archivo

La API acepta texto UTF-8 de hasta 2 MB. Si cambió tras abrirlo, recárgalo para no sobrescribir. El formato se limita a tipos compatibles de menos de 100,000 caracteres y 4,000 líneas; el resaltado se detiene en archivos grandes.

Las ediciones sin guardar quedan como borrador en el navegador, no sustituyen guardar en el espacio persistente.

Se detuvo una tarea o vista

Detener ejecución, vista o reiniciar Libre detiene procesos desechables pero conserva el volumen. Reabre la tarea y reinicia la vista. Eliminar es distinto: tras confirmar, borra definitivamente tarea y espacio.

Problemas de inicio y registro

El primer usuario no es administrador

Solo la primera cuenta de una base nueva se convierte en admin. Las bases existentes conservan roles.

Errores JWT

Define un secreto estable:

JWT_SECRET=replace-with-a-long-random-secret

Cambiar JWT_SECRET invalida sesiones.

Turnstile bloquea el registro

Solo se activa con ambas claves:

TURNSTILE_SITE_KEY=...
TURNSTILE_SECRET_KEY=...

Comprueba que la clave del sitio coincida con el dominio y el secreto sea válido.

Fallan las redirecciones OAuth

Define URL en el proveedor y .env:

BASE_URL=https://your-domain.example
GITHUB_CALLBACK_URL=https://your-domain.example/api/auth/oauth/github/callback
HUGGINGFACE_CALLBACK_URL=https://your-domain.example/api/auth/oauth/huggingface/callback

Problemas del chat documental

Libre WebUI acepta PDF, Office (DOCX/PPTX/XLSX), Markdown, HTML, código y CSV de hasta 10 MB.

Si funciona la búsqueda pero no la recuperación semántica:

  1. Instala un modelo como nomic-embed-text.
  2. Activa embeddings en Ajustes.
  3. Regénéralos desde ajustes o API.
ollama pull nomic-embed-text

La búsqueda por palabras sigue funcionando sin embeddings.

Problemas de vista previa de artefactos

Para juegos o HTML interactivo, pide un archivo HTML completo y autónomo con CSS y JavaScript en línea.

Si necesita teclado:

  • Haz clic dentro de la vista.
  • Utiliza Abrir en su propia pestaña.
  • No dependas de archivos locales ausentes de la respuesta.

Libre puede agrupar bloques comunes index.html + CSS + JavaScript, pero HTML autónomo es más fiable.

Problemas de Docker

El contenedor no llega a Ollama

Usa el archivo externo si Ollama no está en la misma pila:

docker compose -f docker-compose.external-ollama.yml up -d

Los datos no persisten

Monta un volumen persistente y define DATA_DIR si es necesario. La clave se guarda de forma persistente al usar DATA_DIR o Docker.

Restablecer datos locales

Detén la aplicación. Copia y elimina el directorio utilizado. Por defecto es backend/data.

cp -R backend/data backend/data.backup
rm -rf backend/data

Reinicia el backend y crea una cuenta nueva.

¿Sigues atascado?

Abre una incidencia con:

  • Versión y commit de Libre WebUI
  • Método de instalación
  • Sistema operativo
  • Versión de Node.js
  • Versión de Ollama
  • Versión de Docker y resultado de docker info para Work
  • Registros del backend alrededor del fallo
  • Errores de consola del navegador
  • Modelo o proveedor exacto
  • Salida de Actividad de Work cuando falle una tarea o vista