{"record":{"id":"dae6a352dd2eab2a","repo":"django/django","slug":"could-not-find-a-geometry-column-for-s-s","errorCode":null,"errorMessage":"Could not find a geometry column for \"%s\".\"%s\"","messagePattern":"Could not find a geometry column for \"(.+?)\"\\.\"(.+?)\"","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"django/contrib/gis/db/backends/spatialite/introspection.py","lineNumber":40,"sourceCode":"        \"geometrycollection\": \"GeometryField\",\n    }\n\n\nclass SpatiaLiteIntrospection(DatabaseIntrospection):\n    data_types_reverse = GeoFlexibleFieldLookupDict()\n\n    def get_geometry_type(self, table_name, description):\n        with self.connection.cursor() as cursor:\n            # Querying the `geometry_columns` table to get additional metadata.\n            cursor.execute(\n                \"SELECT coord_dimension, srid, geometry_type \"\n                \"FROM geometry_columns \"\n                \"WHERE f_table_name=%s AND f_geometry_column=%s\",\n                (table_name, description.name),\n            )\n            row = cursor.fetchone()\n            if not row:\n                raise Exception(\n                    'Could not find a geometry column for \"%s\".\"%s\"'\n                    % (table_name, description.name)\n                )\n\n            # OGRGeomType does not require GDAL and makes it easy to convert\n            # from OGC geom type name to Django field.\n            ogr_type = row[2]\n            if isinstance(ogr_type, int) and ogr_type > 1000:\n                # SpatiaLite uses SFSQL 1.2 offsets 1000 (Z), 2000 (M), and\n                # 3000 (ZM) to indicate the presence of higher dimensional\n                # coordinates (M not yet supported by Django).\n                ogr_type = ogr_type % 1000 + OGRGeomType.wkb25bit\n            field_type = OGRGeomType(ogr_type).django\n\n            # Getting any GeometryField keyword arguments that are not the\n            # default.\n            dim = row[0]\n            srid = row[1]","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/django/django/blob/ae25a40be07e8a749edf526df37c93e59d4a22c9/django/contrib/gis/db/backends/spatialite/introspection.py#L22-L58","documentation":"Generic Exception raised in SpatiaLiteIntrospection.get_geometry_type when a row for (table_name, description.name) is absent from the geometry_columns table. Django introspects an existing table as a geometry field (via data_types_reverse) but the spatial metadata registry has no entry for that column, so it cannot recover srid/dimension/type.","triggerScenarios":"Triggered by inspectdb, migrations introspection, or any introspection call on a table whose SQLite type was a geometry type but which was created outside SpatiaLite (raw SQL without AddGeometryColumn / no entry in geometry_columns).","commonSituations":"A table created via raw DDL using a geometry-named column type; the geometry_columns metadata row was deleted; the DB was partially initialised (InitSpatialMetaData not run); table created with mod_spatialite disabled for that connection.","solutions":["Register the column properly: `SELECT AddGeometryColumn('table','column', srid, 'POINT', 'XY');` so geometry_columns contains the row.","Run InitSpatialMetaData on the database if geometry_columns itself is empty (see prepare_database).","Skip introspection for that table and hand-write the model with the correct GeometryField subclass.","Confirm the column name and table name in the error match a real geometry column in `SELECT * FROM geometry_columns;`."],"exampleFix":"-- before: column exists but is unregistered\nALTER TABLE my_table ADD COLUMN geom POINT;  -- not a real spatial column\n-- after: register via SpatiaLite so introspection finds it\nSELECT AddGeometryColumn('my_table', 'geom', 4326, 'POINT', 'XY');","handlingStrategy":"validation","validationCode":"# pre-introspection sanity: ensure geometry_columns has the row\nfrom django.db import connection\nwith connection.cursor() as c:\n    c.execute(\"SELECT 1 FROM geometry_columns WHERE f_table_name=%s AND f_geometry_column=%s\", (table, col))\n    if not c.fetchone():\n        raise RuntimeError(f'register column: SELECT AddGeometryColumn(\\'{table}\\',\\'{col}\\',4326,\\'POINT\\',\\'XY\\')')","typeGuard":"def geometry_column_registered(table: str, col: str) -> bool:\n    from django.db import connection\n    with connection.cursor() as c:\n        c.execute('SELECT 1 FROM geometry_columns WHERE f_table_name=%s AND f_geometry_column=%s', (table, col))\n        return c.fetchone() is not None","tryCatchPattern":"from django.contrib.gis.db.backends.spatialite.introspection import SpatiaLiteIntrospection\ntry:\n    field_type, params = introspection.get_geometry_type(table, desc)\nexcept Exception:\n    # register the column via AddGeometryColumn or hand-write the model\n    ...","preventionTips":["Always create geometry columns via AddGeometryColumn, not raw ALTER TABLE.","Run InitSpatialMetaData immediately after creating a new spatialite DB.","Snapshot known-good .sqlite3 files for tests instead of hand-editing schemas."],"tags":["spatialite","introspection","gis","schema"],"analyzedSha":"ae25a40be07e8a749edf526df37c93e59d4a22c9","analyzedAt":"2026-08-06T21:46:51.801Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}