Skip to content

BUG: DataError value too long for type character varying(255) #1381

@gcarq

Description

@gcarq

Describe the bug
DataError: value too long for type character varying(255) is being thrown in AxesDatabaseHandler.user_login_failed when a user with a username longer than 255 characters tries to login.
This is not part of our normal user flow, but happens on a regular basis due to automated scans and there doesn't seem to be a straightforward way to catch this properly.

To Reproduce
Steps to reproduce the behavior:

  1. Navigate to the admin login
  2. Enter a random username that exceeds 255 characters
  3. Enter a random password
  4. Hit login

Expected behavior
Axes catches this login attempt or returns HTTP 400 but not HTTP 500

Your environment
python version: 3.13.7
django version: 5.2.10
django-axes version: 8.1.0
Operating system: Debian Bookworm

Additional context
This error gets thrown when trying to insert AccessAttempt, but its not only limited to that. All models that inherit from AccessBase are affected and also all fields in that model that save user provided data and have a max_length defined.

Traceback (most recent call last):
  File "django/db/models/query.py", line 948, in get_or_create
    return self.get(**kwargs), False
  File "cacheops/query.py", line 346, in get
    return qs._no_monkey.get(qs, *args, **kwargs)
  File "django/db/models/query.py", line 635, in get
    raise self.model.DoesNotExist(
AccessAttempt.DoesNotExist: AccessAttempt matching query does not exist.

Traceback (most recent call last):
  File "django/db/backends/utils.py", line 105, in _execute
    return self.cursor.execute(sql, params)
StringDataRightTruncation: value too long for type character varying(255)

Traceback (most recent call last):
  File "django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "django/utils/decorators.py", line 48, in _wrapper
    return bound_method(*args, **kwargs)
  File "django/views/decorators/cache.py", line 80, in _view_wrapper
    response = view_func(request, *args, **kwargs)
  File "formunauts/core/admin/site/base.py", line 71, in login
    return super().login(request, extra_context)
  File "django/utils/decorators.py", line 48, in _wrapper
    return bound_method(*args, **kwargs)
  File "django/views/decorators/cache.py", line 80, in _view_wrapper
    response = view_func(request, *args, **kwargs)
  File "django/contrib/admin/sites.py", line 449, in login
    return LoginView.as_view(**defaults)(request)
  File "django/views/generic/base.py", line 105, in view
    return self.dispatch(request, *args, **kwargs)
  File "django/utils/decorators.py", line 48, in _wrapper
    return bound_method(*args, **kwargs)
  File "django/utils/decorators.py", line 48, in _wrapper
    return bound_method(*args, **kwargs)
  File "django/views/decorators/debug.py", line 143, in sensitive_post_parameters_wrapper
    return view(request, *args, **kwargs)
  File "django/utils/decorators.py", line 48, in _wrapper
    return bound_method(*args, **kwargs)
  File "django/utils/decorators.py", line 192, in _view_wrapper
    result = _process_exception(request, e)
  File "django/utils/decorators.py", line 190, in _view_wrapper
    response = view_func(request, *args, **kwargs)
  File "django/utils/decorators.py", line 48, in _wrapper
    return bound_method(*args, **kwargs)
  File "django/views/decorators/cache.py", line 80, in _view_wrapper
    response = view_func(request, *args, **kwargs)
  File "django/contrib/auth/views.py", line 89, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "django/views/generic/base.py", line 144, in dispatch
    return handler(request, *args, **kwargs)
  File "django/views/generic/edit.py", line 150, in post
    if form.is_valid():
  File "django/forms/forms.py", line 206, in is_valid
    return self.is_bound and not self.errors
  File "django/forms/forms.py", line 201, in errors
    self.full_clean()
  File "django/forms/forms.py", line 338, in full_clean
    self._clean_form()
  File "django/forms/forms.py", line 354, in _clean_form
    cleaned_data = self.clean()
  File "django/views/decorators/debug.py", line 75, in sensitive_variables_wrapper
    return func(*func_args, **func_kwargs)
  File "django/contrib/auth/forms.py", line 366, in clean
    self.user_cache = authenticate(
  File "django/views/decorators/debug.py", line 75, in sensitive_variables_wrapper
    return func(*func_args, **func_kwargs)
  File "django/contrib/auth/__init__.py", line 126, in authenticate
    user_login_failed.send(
  File "django/dispatch/dispatcher.py", line 189, in send
    response = receiver(signal=self, sender=sender, **named)
  File "axes/signals.py", line 28, in handle_user_login_failed
    AxesProxyHandler.user_login_failed(*args, **kwargs)
  File "axes/helpers.py", line 644, in inner
    return func(*args, **kwargs)
  File "axes/handlers/proxy.py", line 119, in user_login_failed
    return cls.get_implementation().user_login_failed(
  File "axes/handlers/database.py", line 178, in user_login_failed
    ) = AccessAttempt.objects.select_for_update().get_or_create(
  File "django/db/models/query.py", line 955, in get_or_create
    return self.create(**params), True
  File "django/db/models/query.py", line 665, in create
    obj.save(force_insert=True, using=self.db)
  File "django/db/models/base.py", line 902, in save
    self.save_base(
  File "django/db/models/base.py", line 1008, in save_base
    updated = self._save_table(
  File "django/db/models/base.py", line 1169, in _save_table
    results = self._do_insert(
  File "django/db/models/base.py", line 1210, in _do_insert
    return manager._insert(
  File "django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "django/db/models/query.py", line 1873, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "django/db/models/sql/compiler.py", line 1882, in execute_sql
    cursor.execute(sql, params)
  File "cacheops/transaction.py", line 98, in execute
    result = self._no_monkey.execute(self, sql, params)
  File "django/db/backends/utils.py", line 79, in execute
    return self._execute_with_wrappers(
  File "django/db/backends/utils.py", line 92, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "django/db/backends/utils.py", line 100, in _execute
    with self.db.wrap_database_errors:
  File "django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "django/db/backends/utils.py", line 105, in _execute
    return self.cursor.execute(sql, params)
DataError: value too long for type character varying(255)

INSERT INTO axes_accessattempt (user_agent, ip_address, username, http_accept,
                                  path_info, attempt_time, get_data, post_data,
                                  failures_since_start)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s) RETURNING axes_accessattempt.id

Possible implementation
A distinct exception in this case would make things a lot easier to catch this properly

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions