django-postgresql-netfields icon indicating copy to clipboard operation
django-postgresql-netfields copied to clipboard

Database error when receiving IPv6 with scope-id

Open sevdog opened this issue 1 year ago • 7 comments

When receiving an IPv6 there could be a "scope-id" part which is handled and validated by python stdlib.

However the string representation of this kind of value is not valid when used in postgres (see examples in RFC-4007 which raises an error

invalid input syntax for type inet: "fe80::1234%ne0"

Thus the db-prep value should not be the str representation of IPv6 addresses.

sevdog avatar Dec 17 '24 13:12 sevdog

Internally django uses ipaddresse to validate IPv6 and uses a hack to remove the scope-id part:

https://github.com/django/django/blame/7e41a7a47d0ee3e2d8270b04afbb908ece0b2b77/django/utils/ipv6.py#L27

sevdog avatar Dec 17 '24 13:12 sevdog

I just made a test to prepare to fix this:

    def test_ipv6_strip_scope(self):
        instance = self.model.objects.create(field='2001:db8::1%foo')
        instance = self.model.objects.get(pk=instance.pk)
        self.assertEqual(str(instance.field), '2001:db8::1')

However, it is only failing on Python 3.8, and for a different reason:

  File "/usr/lib64/python3.8/ipaddress.py", line 118, in ip_interface
    raise ValueError('%r does not appear to be an IPv4 or IPv6 interface' %
ValueError: '2001:db8::1%foo' does not appear to be an IPv4 or IPv6 interface

It works fine on Python versions 3.9-3.13 with Django versions 1.11-5.2.

Is this still an issue for you?

jimfunk avatar Jul 25 '25 10:07 jimfunk

For me is fine, since my projects works on Python 3.12+ and Django 4.2+ :)

Also Python 3.8 is EOL since October 2024 (source: https://devguide.python.org/versions/), thus I think it is ok that it does not work with that version of Python.

PS: IPv6 has too many representations for me.

sevdog avatar Jul 25 '25 14:07 sevdog

OK, have you re-checked in your environments? There is a possibility that the original issue is handled in new psycopg3 or PostgreSQL. (I tested against 17)

jimfunk avatar Jul 25 '25 14:07 jimfunk

I got this from an application running on PostgreSQL 15, the error is raised directly from the DB.

In my current environment the problem was workarounded by striping out the scope-id at the source.

When I try to run the insert for my model I still get the error.

from django.db import models
from netfields import InetAddressField

class IpModel(models.Model):
    ip = InetAddressField(null=True, blank=True)


IpModel.objects.create(ip='2001:db8::1%foo')
# DataError: invalid input syntax for type inet: "2001:db8::1%foo/128"

Currently I have psycopg 3.2.9 installed from source: psycopg[c]==3.2.9 (long story short: uwsgi and psycopg do not get along when compiled against different versions of OpenSSL).

sevdog avatar Jul 25 '25 16:07 sevdog

I just tried the latest version from github an I stil get the same error.

sevdog avatar Jul 25 '25 16:07 sevdog

Thanks. It looks like it was probably handled in either PostgreSQL 16 or 17.

I will spin up an older environment and try to replicate.

jimfunk avatar Jul 25 '25 16:07 jimfunk