{"id":"28f11888704d72ca","repo":"psycopg/psycopg2","slug":"range-types-not-available-in-version-s","errorCode":null,"errorMessage":"range types not available in version %s","messagePattern":"range types not available in version (.+?)","errorType":"exception","errorClass":"ProgrammingError","httpStatus":null,"severity":"error","filePath":"lib/_range.py","lineNumber":352,"sourceCode":"        except TypeError:\n            pass\n\n        if self.range is None:\n            raise TypeError(\n                'pyrange must be a type or a Range strict subclass')\n\n    @classmethod\n    def _from_db(self, name, pyrange, conn_or_curs):\n        \"\"\"Return a `RangeCaster` instance for the type *pgrange*.\n\n        Raise `ProgrammingError` if the type is not found.\n        \"\"\"\n        from psycopg2.extensions import STATUS_IN_TRANSACTION\n        from psycopg2.extras import _solve_conn_curs\n        conn, curs = _solve_conn_curs(conn_or_curs)\n\n        if conn.info.server_version < 90200:\n            raise ProgrammingError(\"range types not available in version %s\"\n                % conn.info.server_version)\n\n        # Store the transaction status of the connection to revert it after use\n        conn_status = conn.status\n\n        # Use the correct schema\n        if '.' in name:\n            schema, tname = name.split('.', 1)\n        else:\n            tname = name\n            schema = 'public'\n\n        # get the type oid and attributes\n        curs.execute(\"\"\"\\\nselect rngtypid, rngsubtype, typarray\nfrom pg_range r\njoin pg_type t on t.oid = rngtypid\njoin pg_namespace ns on ns.oid = typnamespace","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/psycopg/psycopg2/blob/3a6d9d6ddc6b53eaa80b712f5fa6b23abbdc38db/lib/_range.py#L334-L370","documentation":"Raised by RangeCaster._from_db() (lib/_range.py:351-353) when the connected PostgreSQL server reports a version below 9.2 (server_version < 90200). Range types (int4range, daterange, tsrange, etc.) were introduced in PostgreSQL 9.2, so querying pg_range on an older server is meaningless and the function refuses to proceed.","triggerScenarios":"Calling register_range(pgrange, pyrange, conn_or_curs) or otherwise invoking RangeCaster._from_db() against a database whose server version is < 9.2. The check reads conn.info.server_version.","commonSituations":"Connecting to a legacy PostgreSQL deployment (8.x, 9.0, 9.1) still common in older on-premise or appliance environments. Also seen when a connection string accidentally points to a standby/replica running an older major version, or after a botched upgrade.","solutions":["Upgrade the PostgreSQL server to 9.2 or newer (9.2 is itself ancient; prefer a supported major version).","Verify the connection target with 'SELECT version();' and fix the DSN/host if it points to the wrong server.","If upgrade is impossible, avoid the range API entirely and model the data with separate columns."],"exampleFix":"// before\nregister_range('int4range', NumericRange, old_conn)  # server is 9.1\n// after\n# point at an upgraded server (9.2+) then:\nregister_range('int4range', NumericRange, new_conn)","handlingStrategy":"validation","validationCode":"if conn.info.server_version < 90200:\n    raise RuntimeError(f'range types require PostgreSQL >= 9.2, got {conn.info.server_version}')","typeGuard":"def server_supports_ranges(conn) -> bool:\n    return conn.info.server_version >= 90200","tryCatchPattern":"try:\n    caster = register_range(name, pyrange, conn)\nexcept ProgrammingError as e:\n    if 'range types not available' in str(e):\n        # fall back to non-range representation\n        pass\n    else: raise","preventionTips":["Check SELECT version() / server_version before registering range casters.","Gate range-dependent features behind a server-version capability check."],"tags":["version","range","postgresql","server-version","programming-error"],"analyzedSha":"3a6d9d6ddc6b53eaa80b712f5fa6b23abbdc38db","analyzedAt":"2026-08-04T19:56:51.958Z","schemaVersion":2}