Errores: qué significan y qué hacer¶
Cómo se leen los errores de tai-sql¶
Un problema que tú puedes arreglar nunca sale como traceback. Sale así:
❌ La variable de entorno MAIN_DATABASE_URL no está definida
💡 Defínela en tu entorno o en el fichero .env: MAIN_DATABASE_URL=postgresql://usuario:clave@host:5432/basededatos
📍 Schema 'public'
🔗 E011
Cuatro partes: qué ha pasado, qué hacer —siempre está: si falta, es un bug de tai-sql—, dónde, y un código para buscarlo.
Si en vez de eso ves ❌ Error interno de tai-sql: ..., no es culpa de tu schema: es un fallo
del framework. Repite con tai-sql --debug <comando> para la traza y
repórtalo.
| Rango | Familia |
|---|---|
| E001–E010 | Definición del schema: tipos, campos, relaciones, constraints, vistas |
| E011–E015 | Entorno y proyecto: variables, proyecto no encontrado, schema no encontrado |
| E020–E023 | Base de datos: conexión, base inexistente, operación fallida, operación insegura |
| E030 | Generación de recursos |
Los que más se repiten¶
La variable de entorno X no está definida (E011)
El datasource(provider=env('X')) se resuelve al importar el schema, así que este error
aparece en cualquier comando, no solo en los que se conectan.
Comprueba que la variable está exportada, y que el proceso la ve: tai-sql no carga .env
por su cuenta salvo que el proyecto lo haga.
No estás dentro de un proyecto tai-sql (E012)
No hay ningún .taisqlproject por encima del directorio actual. O estás en el sitio
equivocado, o el proyecto no se creó con tai-sql init.
El schema 'X' no existe en este proyecto (E013)
El nombre que va en --schema es el del fichero schemas/<nombre>.py, no el nombre del
schema en la base de datos. Pueden ser distintos: el segundo es el de
datasource(schema=...).
El fichero del schema 'X' tiene un error de sintaxis (E014)
Python no puede importar el fichero. Casi siempre es una de dos: falta
from __future__ import annotations, o hay una referencia a una clase declarada más abajo
sin él.
La tabla 'X' no declara __tablename__ (E002)
Toda Table y toda View lo necesitan: es el nombre físico en la base de datos.
La tabla 'X' no tiene clave primaria (E002)
Marca al menos una columna con column(primary_key=True). Sin ella no se puede generar el
DAO ni comparar el estado con la base de datos.
relation() se ha declarado sin 'backref' (E003)
fields, references y backref son obligatorios. El backref es el nombre que tendrá la
relación en el otro extremo.
La relación 'X.y' apunta a 'Z', que no está declarado en este schema (E003)
La tabla destino no está en este schema. Las relaciones entre schemas distintos no se declaran: son dos bases de datos lógicas separadas.
La columna calculada 'X' no declara tipo de retorno (E001)
Una calculada necesita anotación de retorno: -> col[str] en v2, o @calculated_column con
-> str en v1.
Hay operaciones que no se pueden ejecutar sobre los datos actuales (E023)
Es el BLOCKED del push. Lo que hay arriba en la salida dice cuál: NULLs en una columna que
pasa a obligatoria, duplicados en una que pasa a única, huérfanos en una FK nueva. Se
arreglan con los datos, no con el schema:
La base de datos 'X' no existe en el servidor (E021)
El servidor responde pero la base de datos no está. tai-sql push la crea; tai-sql ping -d
te dice si existe sin tocar nada.
Los que no dan error, que son los caros¶
Estos no revientan. Se manifiestan como «no funciona» horas después.
El cliente generado no refleja el schema¶
En orden de probabilidad:
- No has regenerado.
tai-sql generate, otai-sql push—que regenera al terminar, pero solo si hubo cambios en la base de datos: si tocaste algo que no produce DDL, no regenera nada. - Estás importando otra copia. Si hay una copia vieja en
site-packageso en otra ruta delsys.path, gana esa. - Editaste el código generado. Se pisó.
- El método que esperabas como columna no lo es. Un método con
-> strdesnudo y sin@calculated_columnes solo un método: no genera columna, y no avisa.
Qué hacer: borrar el directorio generado entero y tai-sql generate. Si después de eso
sigue faltando, el problema está en el schema.
push dice que no hay cambios y tú ves que sí¶
- Convertir una columna en autoincremental. No se puede aplicar —exige crear una secuencia o una identidad—, así que tampoco se reporta. Hazlo a mano.
- Un índice creado a mano que el schema no declara: no se elimina nunca, a propósito.
- Estás mirando otra base de datos. Con
env(), la URL sale del entorno del proceso: comprueba contai-sql infoa qué apunta de verdad.
Las relaciones se declararon en los dos lados¶
Si relation() está en las dos tablas, tai-sql crea dos claves foráneas donde debería haber
una. Se declara solo en la tabla que tiene las columnas FK.
feed falla con una columna vectorial que declara encoder¶
El encoder real vive en el cliente generado, no en tai-sql. Aporta el vector ya calculado en el
feed(), o puebla esa columna desde el cliente.
Conexión y permisos¶
tai-sql ping -s <schema> # ¿responde el servidor?
tai-sql ping -s <schema> -d # ¿existe además la base de datos?
tai-sql info # ¿a qué está apuntando de verdad?
| Síntoma | Qué mirar |
|---|---|
ModuleNotFoundError de un driver al conectar |
Falta el extra del motor: pip install 'tai-sql[mysql]', [sqlserver], [bigquery]. PostgreSQL no necesita ninguno |
| Timeout al conectar | Host y puerto de la URL; firewall; si el servidor está en Docker, el nombre de red |
password authentication failed |
La URL. Si la contraseña lleva caracteres especiales, tienen que ir escapados |
permission denied for schema |
El usuario necesita CREATE en el schema para el push, no solo SELECT/INSERT |
permission denied to create database |
push intenta crear la base de datos si no existe. O se la creas tú, o le das el permiso |
La extensión vector no se puede crear |
Instala pgvector en el servidor; CREATE EXTENSION necesita superusuario |
Cómo diagnosticar cualquier cosa, en orden¶
tai-sql info— ¿carga el schema? ¿qué tablas ve? ¿a qué base apunta?tai-sql ping -d— ¿llega?tai-sql push --dry-run --verbose— ¿qué DDL saldría?tai-sql generate— ¿el cliente se regenera sin fallos?tai-sql --debug <comando>— si algo sale como error interno, la traza.
Los pasos 1 a 3 no modifican nada: se pueden ejecutar siempre.