diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3a3f69935afa2809c79ae5bd1bf2bd1728006978..19b36d46b5043ac1f767ee1b520322e33895f198 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,50 @@
 # CHANGELOG
 
 
+## v0.144.3 (2025-02-14)
+
+### Bug Fixes
+
+- Non unique name during wheel upload
+  ([#1527](https://github.com/python-zeroconf/python-zeroconf/pull/1527),
+  [`43136fa`](https://github.com/python-zeroconf/python-zeroconf/commit/43136fa418d4d7826415e1d0f7761b198347ced7))
+
+
+## v0.144.2 (2025-02-14)
+
+### Bug Fixes
+
+- Add a helpful hint for when EADDRINUSE happens during startup
+  ([#1526](https://github.com/python-zeroconf/python-zeroconf/pull/1526),
+  [`48dbb71`](https://github.com/python-zeroconf/python-zeroconf/commit/48dbb7190a4f5126e39dbcdb87e34380d4562cd0))
+
+
+## v0.144.1 (2025-02-12)
+
+### Bug Fixes
+
+- Wheel builds failing after adding armv7l builds
+  ([#1518](https://github.com/python-zeroconf/python-zeroconf/pull/1518),
+  [`e7adac9`](https://github.com/python-zeroconf/python-zeroconf/commit/e7adac9c59fc4d0c4822c6097a4daee3d68eb4de))
+
+
+## v0.144.0 (2025-02-12)
+
+### Features
+
+- Add armv7l wheel builds ([#1517](https://github.com/python-zeroconf/python-zeroconf/pull/1517),
+  [`39887b8`](https://github.com/python-zeroconf/python-zeroconf/commit/39887b80328d616e8e6f6ca9d08aecc06f7b0711))
+
+
+## v0.143.1 (2025-02-12)
+
+### Bug Fixes
+
+- Make no buffer space available when adding multicast memberships forgiving
+  ([#1516](https://github.com/python-zeroconf/python-zeroconf/pull/1516),
+  [`f377d5c`](https://github.com/python-zeroconf/python-zeroconf/commit/f377d5cd08d724282c8487785163b466f3971344))
+
+
 ## v0.143.0 (2025-01-31)
 
 ### Features
diff --git a/PKG-INFO b/PKG-INFO
index daa5a466fdffc7b274e408cc9c0f24fcbd626c92..079aeb5578a749257263e24a4041d7f7efb9ef00 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 2.3
 Name: zeroconf
-Version: 0.143.0
+Version: 0.144.3
 Summary: A pure python implementation of multicast DNS service discovery
 License: LGPL-2.1-or-later
 Author: Paul Scott-Murphy
diff --git a/build_ext.py b/build_ext.py
index 26b4eb96f3910ad3c385ce475ca5f773fb606c12..e91f6350f35ac276ab75b8de00b83cbc05335553 100644
--- a/build_ext.py
+++ b/build_ext.py
@@ -54,4 +54,3 @@ def build(setup_kwargs: Any) -> None:
     except Exception:
         if os.environ.get("REQUIRE_CYTHON"):
             raise
-        pass
diff --git a/pyproject.toml b/pyproject.toml
index 72728b5ba94fc550139499cab7f2a8b6e8f2f72c..4015b88f62bc2c4aaead90e9ad8397dea8c19547 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "zeroconf"
-version = "0.143.0"
+version = "0.144.3"
 description = "A pure python implementation of multicast DNS service discovery"
 authors = ["Paul Scott-Murphy", "William McBrine", "Jakub Stasiak", "J. Nick Koston"]
 license = "LGPL-2.1-or-later"
@@ -86,13 +86,31 @@ sphinx = "^7.4.7 || ^8.1.3"
 sphinx-rtd-theme = "^3.0.2"
 
 [tool.ruff]
-target-version = "py38"
+target-version = "py39"
 line-length = 110
 
 [tool.ruff.lint]
 ignore = [
     "S101", # use of assert
     "S104",  # S104 Possible binding to all interfaces
+    "PLR0912", # too many to fix right now
+    "TC001", # too many to fix right now
+    "TID252", # skip
+    "PLR0913", # too late to make changes here
+    "PLR0911", # would be breaking change
+    "TRY003", # too many to fix
+    "SLF001", # design choice
+    "TC003", # too many to fix
+    "PLR2004" , # too many to fix
+    "PGH004",  # too many to fix
+    "PGH003", # too many to fix
+    "SIM110", # this is slower
+    "FURB136", # this is slower for Cython
+    "PYI034", # enable when we drop Py3.10
+    "PYI032", # breaks Cython
+    "PYI041",  # breaks Cython
+    "FURB188", # usually slower
+    "PERF401", # Cython: closures inside cpdef functions not yet supported
 ]
 select = [
     "B",   # flake8-bugbear
@@ -104,8 +122,67 @@ select = [
     "UP",  # pyupgrade
     "I",   # isort
     "RUF", # ruff specific
+    "FLY", # flynt
+    "FURB", # refurb
+    "G", # flake8-logging-format   ,
+    "PERF", # Perflint
+    "PGH", # pygrep-hooks
+    "PIE", # flake8-pie
+    "PL", # pylint
+    "PT", # flake8-pytest-style
+    "PTH", # flake8-pathlib
+    "PYI", # flake8-pyi
+    "RET", # flake8-return
+    "RSE", # flake8-raise    ,
+    "SIM", # flake8-simplify
+    "SLF", # flake8-self
+    "SLOT", # flake8-slots
+    "T100", # Trace found: {name} used
+    "T20", # flake8-print
+    "TC", # flake8-type-checking
+    "TID", # Tidy imports
+    "TRY", # tryceratops
 ]
 
+[tool.ruff.lint.per-file-ignores]
+"tests/**/*" = [
+    "D100",
+    "D101",
+    "D102",
+    "D103",
+    "D104",
+    "S101",
+    "SLF001",
+    "PLR2004", # too many to fix right now
+    "PT011", # too many to fix right now
+    "PT006", # too many to fix right now
+    "PGH003", # too many to fix right now
+    "PT007", # too many to fix right now
+    "PT027",  # too many to fix right now
+    "PLW0603" , # too many to fix right now
+    "PLR0915", # too many to fix right now
+    "FLY002", # too many to fix right now
+    "PT018", # too many to fix right now
+    "PLR0124", # too many to fix right now
+    "SIM202" , # too many to fix right now
+    "PT012" , # too many to fix right now
+    "TID252", # too many to fix right now
+    "PLR0913", # skip this one
+    "SIM102" , # too many to fix right now
+    "SIM108", # too many to fix right now
+    "TC003",  # too many to fix right now
+    "TC002", # too many to fix right now
+    "T201", # too many to fix right now
+]
+"bench/**/*" = [
+    "T201", # intended
+]
+"examples/**/*" = [
+    "T201", # intended
+]
+"setup.py" = ["D100"]
+"conftest.py" = ["D100"]
+"docs/conf.py" = ["D100"]
 
 [tool.pylint.BASIC]
 class-const-naming-style = "any"
@@ -162,15 +239,21 @@ profile = "black"
 known_first_party = ["zeroconf", "tests"]
 
 [tool.mypy]
+warn_unused_configs = true
 check_untyped_defs = true
 disallow_any_generics = false  # turn this on when we drop 3.7/3.8 support
 disallow_incomplete_defs = true
 disallow_untyped_defs = true
+warn_incomplete_stub = true
 mypy_path = "src/"
-no_implicit_optional = true
 show_error_codes = true
+warn_redundant_casts = false  # Activate for cleanup.
+warn_return_any = true
 warn_unreachable = true
-warn_unused_ignores = false
+warn_unused_ignores = false  # Does not always work properly, activate for cleanup.
+extra_checks = true
+strict_equality = true
+strict_bytes = true  # Will be true by default with mypy v2 release.
 exclude = [
     'docs/*',
     'bench/*',
@@ -198,5 +281,5 @@ build-backend = "poetry.core.masonry.api"
 ignore-words-list = ["additionals", "HASS"]
 
 [tool.cython-lint]
-max-line-length = 88
+max-line-length = 110
 ignore = ['E501'] # too many to fix right now
diff --git a/setup.py b/setup.py
index bcd677386bb6697f9975aecf5a630b0a9fae040f..2d0b41f92314b65e1b51d89ba39d622872348def 100644
--- a/setup.py
+++ b/setup.py
@@ -19,7 +19,7 @@ install_requires = \
 
 setup_kwargs = {
     'name': 'zeroconf',
-    'version': '0.143.0',
+    'version': '0.144.3',
     'description': 'A pure python implementation of multicast DNS service discovery',
     'long_description': 'python-zeroconf\n===============\n\n.. image:: https://github.com/python-zeroconf/python-zeroconf/workflows/CI/badge.svg\n   :target: https://github.com/python-zeroconf/python-zeroconf?query=workflow%3ACI+branch%3Amaster\n\n.. image:: https://img.shields.io/pypi/v/zeroconf.svg\n    :target: https://pypi.python.org/pypi/zeroconf\n\n.. image:: https://codecov.io/gh/python-zeroconf/python-zeroconf/branch/master/graph/badge.svg\n   :target: https://codecov.io/gh/python-zeroconf/python-zeroconf\n\n.. image:: https://img.shields.io/endpoint?url=https://codspeed.io/badge.json\n   :target: https://codspeed.io/python-zeroconf/python-zeroconf\n   :alt: Codspeed.io status for python-zeroconf\n\n.. image:: https://readthedocs.org/projects/python-zeroconf/badge/?version=latest\n    :target: https://python-zeroconf.readthedocs.io/en/latest/?badge=latest\n    :alt: Documentation Status\n\n`Documentation <https://python-zeroconf.readthedocs.io/en/latest/>`_.\n\nThis is fork of pyzeroconf, Multicast DNS Service Discovery for Python,\noriginally by Paul Scott-Murphy (https://github.com/paulsm/pyzeroconf),\nmodified by William McBrine (https://github.com/wmcbrine/pyzeroconf).\n\nThe original William McBrine\'s fork note::\n\n    This fork is used in all of my TiVo-related projects: HME for Python\n    (and therefore HME/VLC), Network Remote, Remote Proxy, and pyTivo.\n    Before this, I was tracking the changes for zeroconf.py in three\n    separate repos. I figured I should have an authoritative source.\n\n    Although I make changes based on my experience with TiVos, I expect that\n    they\'re generally applicable. This version also includes patches found\n    on the now-defunct (?) Launchpad repo of pyzeroconf, and elsewhere\n    around the net -- not always well-documented, sorry.\n\nCompatible with:\n\n* Bonjour\n* Avahi\n\nCompared to some other Zeroconf/Bonjour/Avahi Python packages, python-zeroconf:\n\n* isn\'t tied to Bonjour or Avahi\n* doesn\'t use D-Bus\n* doesn\'t force you to use particular event loop or Twisted (asyncio is used under the hood but not required)\n* is pip-installable\n* has PyPI distribution\n* has an optional cython extension for performance (pure python is supported as well)\n\nPython compatibility\n--------------------\n\n* CPython 3.9+\n* PyPy 3.9+\n\nVersioning\n----------\n\nThis project uses semantic versioning.\n\nStatus\n------\n\nThis project is actively maintained.\n\nTraffic Reduction\n-----------------\n\nBefore version 0.32, most traffic reduction techniques described in https://datatracker.ietf.org/doc/html/rfc6762#section-7\nwhere not implemented which could lead to excessive network traffic.  It is highly recommended that version 0.32 or later\nis used if this is a concern.\n\nIPv6 support\n------------\n\nIPv6 support is relatively new and currently limited, specifically:\n\n* `InterfaceChoice.All` is an alias for `InterfaceChoice.Default` on non-POSIX\n  systems.\n* Dual-stack IPv6 sockets are used, which may not be supported everywhere (some\n  BSD variants do not have them).\n* Listening on localhost (`::1`) does not work. Help with understanding why is\n  appreciated.\n\nHow to get python-zeroconf?\n===========================\n\n* PyPI page https://pypi.org/project/zeroconf/\n* GitHub project https://github.com/python-zeroconf/python-zeroconf\n\nThe easiest way to install python-zeroconf is using pip::\n\n    pip install zeroconf\n\n\n\nHow do I use it?\n================\n\nHere\'s an example of browsing for a service:\n\n.. code-block:: python\n\n    from zeroconf import ServiceBrowser, ServiceListener, Zeroconf\n\n\n    class MyListener(ServiceListener):\n\n        def update_service(self, zc: Zeroconf, type_: str, name: str) -> None:\n            print(f"Service {name} updated")\n\n        def remove_service(self, zc: Zeroconf, type_: str, name: str) -> None:\n            print(f"Service {name} removed")\n\n        def add_service(self, zc: Zeroconf, type_: str, name: str) -> None:\n            info = zc.get_service_info(type_, name)\n            print(f"Service {name} added, service info: {info}")\n\n\n    zeroconf = Zeroconf()\n    listener = MyListener()\n    browser = ServiceBrowser(zeroconf, "_http._tcp.local.", listener)\n    try:\n        input("Press enter to exit...\\n\\n")\n    finally:\n        zeroconf.close()\n\n.. note::\n\n    Discovery and service registration use *all* available network interfaces by default.\n    If you want to customize that you need to specify ``interfaces`` argument when\n    constructing ``Zeroconf`` object (see the code for details).\n\nIf you don\'t know the name of the service you need to browse for, try:\n\n.. code-block:: python\n\n    from zeroconf import ZeroconfServiceTypes\n    print(\'\\n\'.join(ZeroconfServiceTypes.find()))\n\nSee examples directory for more.\n\nChangelog\n=========\n\n`Changelog <CHANGELOG.md>`_\n\nLicense\n=======\n\nLGPL, see COPYING file for details.\n',
     'author': 'Paul Scott-Murphy',
diff --git a/src/zeroconf/__init__.py b/src/zeroconf/__init__.py
index b85aee743f9d6bbf5ac20fbdce517e0287e2241e..59052702e7ad4aadfa9617eb7c5c8668f76a8644 100644
--- a/src/zeroconf/__init__.py
+++ b/src/zeroconf/__init__.py
@@ -88,7 +88,7 @@ from ._utils.time import (  # noqa # import needed for backwards compat
 
 __author__ = "Paul Scott-Murphy, William McBrine"
 __maintainer__ = "Jakub Stasiak <jakub@stasiak.at>"
-__version__ = "0.143.0"
+__version__ = "0.144.3"
 __license__ = "LGPL"
 
 
diff --git a/src/zeroconf/_cache.py b/src/zeroconf/_cache.py
index 5ac43f30736dd5d7fe98d74480d01203c211b9db..c8e2686ee3417ad0319f6ed34cdbdbf0dc0d0df3 100644
--- a/src/zeroconf/_cache.py
+++ b/src/zeroconf/_cache.py
@@ -22,8 +22,9 @@ USA
 
 from __future__ import annotations
 
+from collections.abc import Iterable
 from heapq import heapify, heappop, heappush
-from typing import Dict, Iterable, Union, cast
+from typing import Union, cast
 
 from ._dns import (
     DNSAddress,
@@ -40,7 +41,7 @@ from .const import _ONE_SECOND, _TYPE_PTR
 
 _UNIQUE_RECORD_TYPES = (DNSAddress, DNSHinfo, DNSPointer, DNSText, DNSService)
 _UniqueRecordsType = Union[DNSAddress, DNSHinfo, DNSPointer, DNSText, DNSService]
-_DNSRecordCacheType = Dict[str, Dict[DNSRecord, DNSRecord]]
+_DNSRecordCacheType = dict[str, dict[DNSRecord, DNSRecord]]
 _DNSRecord = DNSRecord
 _str = str
 _float = float
diff --git a/src/zeroconf/_core.py b/src/zeroconf/_core.py
index 3f007c1743aa77849c5f8a0d484abce991eb4d3d..5e3a7f46518daada87ffa921a28d109998f39d2e 100644
--- a/src/zeroconf/_core.py
+++ b/src/zeroconf/_core.py
@@ -26,8 +26,8 @@ import asyncio
 import logging
 import sys
 import threading
+from collections.abc import Awaitable
 from types import TracebackType
-from typing import Awaitable
 
 from ._cache import DNSCache
 from ._dns import DNSQuestion, DNSQuestionType
diff --git a/src/zeroconf/_dns.py b/src/zeroconf/_dns.py
index bc0a3948e534c4eab63817d1716d6ca09612d50e..591eb0183a0d3519a65fadc862765be4ebd87de0 100644
--- a/src/zeroconf/_dns.py
+++ b/src/zeroconf/_dns.py
@@ -79,7 +79,7 @@ class DNSEntry:
         self.class_ = class_ & _CLASS_MASK
         self.unique = (class_ & _CLASS_UNIQUE) != 0
 
-    def _dns_entry_matches(self, other) -> bool:  # type: ignore[no-untyped-def]
+    def _dns_entry_matches(self, other: DNSEntry) -> bool:
         return self.key == other.key and self.type == other.type and self.class_ == other.class_
 
     def __eq__(self, other: Any) -> bool:
@@ -135,7 +135,7 @@ class DNSQuestion(DNSEntry):
     @property
     def max_size(self) -> int:
         """Maximum size of the question in the packet."""
-        return len(self.name.encode("utf-8")) + _LEN_BYTE + _LEN_SHORT + _LEN_SHORT  # type  # class
+        return len(self.name.encode("utf-8")) + _LEN_BYTE + _LEN_SHORT + _LEN_SHORT
 
     @property
     def unicast(self) -> bool:
@@ -199,7 +199,7 @@ class DNSRecord(DNSEntry):
                 return True
         return False
 
-    def _suppressed_by_answer(self, other) -> bool:  # type: ignore[no-untyped-def]
+    def _suppressed_by_answer(self, other: DNSRecord) -> bool:
         """Returns true if another record has same name, type and class,
         and if its TTL is at least half of this record's."""
         return self == other and other.ttl > (self.ttl / 2)
@@ -285,7 +285,7 @@ class DNSAddress(DNSRecord):
         """Tests equality on address"""
         return isinstance(other, DNSAddress) and self._eq(other)
 
-    def _eq(self, other) -> bool:  # type: ignore[no-untyped-def]
+    def _eq(self, other: DNSAddress) -> bool:
         return (
             self.address == other.address
             and self.scope_id == other.scope_id
@@ -344,7 +344,7 @@ class DNSHinfo(DNSRecord):
         """Tests equality on cpu and os."""
         return isinstance(other, DNSHinfo) and self._eq(other)
 
-    def _eq(self, other) -> bool:  # type: ignore[no-untyped-def]
+    def _eq(self, other: DNSHinfo) -> bool:
         """Tests equality on cpu and os."""
         return self.cpu == other.cpu and self.os == other.os and self._dns_entry_matches(other)
 
@@ -399,7 +399,7 @@ class DNSPointer(DNSRecord):
         """Tests equality on alias."""
         return isinstance(other, DNSPointer) and self._eq(other)
 
-    def _eq(self, other) -> bool:  # type: ignore[no-untyped-def]
+    def _eq(self, other: DNSPointer) -> bool:
         """Tests equality on alias."""
         return self.alias_key == other.alias_key and self._dns_entry_matches(other)
 
@@ -447,7 +447,7 @@ class DNSText(DNSRecord):
         """Tests equality on text."""
         return isinstance(other, DNSText) and self._eq(other)
 
-    def _eq(self, other) -> bool:  # type: ignore[no-untyped-def]
+    def _eq(self, other: DNSText) -> bool:
         """Tests equality on text."""
         return self.text == other.text and self._dns_entry_matches(other)
 
@@ -510,7 +510,7 @@ class DNSService(DNSRecord):
         """Tests equality on priority, weight, port and server"""
         return isinstance(other, DNSService) and self._eq(other)
 
-    def _eq(self, other) -> bool:  # type: ignore[no-untyped-def]
+    def _eq(self, other: DNSService) -> bool:
         """Tests equality on priority, weight, port and server."""
         return (
             self.priority == other.priority
@@ -585,7 +585,7 @@ class DNSNsec(DNSRecord):
         """Tests equality on next_name and rdtypes."""
         return isinstance(other, DNSNsec) and self._eq(other)
 
-    def _eq(self, other) -> bool:  # type: ignore[no-untyped-def]
+    def _eq(self, other: DNSNsec) -> bool:
         """Tests equality on next_name and rdtypes."""
         return (
             self.next_name == other.next_name
diff --git a/src/zeroconf/_handlers/answers.py b/src/zeroconf/_handlers/answers.py
index ec53eb84295035473ce197baca4a17e790e5e15f..07b0a65ab96b4769d5aae39fbdd6e2320e2df1a9 100644
--- a/src/zeroconf/_handlers/answers.py
+++ b/src/zeroconf/_handlers/answers.py
@@ -23,13 +23,12 @@ USA
 from __future__ import annotations
 
 from operator import attrgetter
-from typing import Dict, Set
 
 from .._dns import DNSQuestion, DNSRecord
 from .._protocol.outgoing import DNSOutgoing
 from ..const import _FLAGS_AA, _FLAGS_QR_RESPONSE
 
-_AnswerWithAdditionalsType = Dict[DNSRecord, Set[DNSRecord]]
+_AnswerWithAdditionalsType = dict[DNSRecord, set[DNSRecord]]
 
 int_ = int
 
diff --git a/src/zeroconf/_history.py b/src/zeroconf/_history.py
index 5bae7be048ce0f9d8cd0d45a0fe49078fd163161..1b6f3fadf2ada5c3f748b81d6f542fb1cfe4d962 100644
--- a/src/zeroconf/_history.py
+++ b/src/zeroconf/_history.py
@@ -60,9 +60,7 @@ class QuestionHistory:
             return False
         # The last question has more known answers than
         # we knew so we have to ask
-        if previous_known_answers - known_answers:
-            return False
-        return True
+        return not previous_known_answers - known_answers
 
     def async_expire(self, now: _float) -> None:
         """Expire the history of old questions."""
diff --git a/src/zeroconf/_listener.py b/src/zeroconf/_listener.py
index 925c689e0ce6ec3f24ae0f672516de0038feb5ad..ed50316985e5636b508e7e24d2cd9ec98e2cf655 100644
--- a/src/zeroconf/_listener.py
+++ b/src/zeroconf/_listener.py
@@ -26,7 +26,7 @@ import asyncio
 import logging
 import random
 from functools import partial
-from typing import TYPE_CHECKING, Tuple, cast
+from typing import TYPE_CHECKING, cast
 
 from ._logger import QuietLogger, log
 from ._protocol.incoming import DNSIncoming
@@ -131,14 +131,14 @@ class AsyncListener:
         if len(addrs) == 2:
             v6_flow_scope: tuple[()] | tuple[int, int] = ()
             # https://github.com/python/mypy/issues/1178
-            addr, port = addrs  # type: ignore
+            addr, port = addrs
             addr_port = addrs
             if TYPE_CHECKING:
-                addr_port = cast(Tuple[str, int], addr_port)
+                addr_port = cast(tuple[str, int], addr_port)
             scope = None
         else:
             # https://github.com/python/mypy/issues/1178
-            addr, port, flow, scope = addrs  # type: ignore
+            addr, port, flow, scope = addrs
             if debug:  # pragma: no branch
                 log.debug("IPv6 scope_id %d associated to the receiving interface", scope)
             v6_flow_scope = (flow, scope)
diff --git a/src/zeroconf/_protocol/incoming.py b/src/zeroconf/_protocol/incoming.py
index 7f4a8eec1c71c1058031dc213bfad7b6a3d5a4c2..2d977b642e99b32cf8166ca29c589835843e9d4a 100644
--- a/src/zeroconf/_protocol/incoming.py
+++ b/src/zeroconf/_protocol/incoming.py
@@ -398,7 +398,7 @@ class DNSIncoming:
             bitmap_length = view[offset_plus_one]
             bitmap_end = offset_plus_two + bitmap_length
             for i, byte in enumerate(self.data[offset_plus_two:bitmap_end]):
-                for bit in range(0, 8):
+                for bit in range(8):
                     if byte & (0x80 >> bit):
                         rdtypes.append(bit + window * 256 + i * 8)
             self.offset += 2 + bitmap_length
diff --git a/src/zeroconf/_protocol/outgoing.py b/src/zeroconf/_protocol/outgoing.py
index f5d0982110e1c7cffae7a465f26fd8925a93aab5..fd5e57a023ab084d6709cbc9a3decc517ab931fe 100644
--- a/src/zeroconf/_protocol/outgoing.py
+++ b/src/zeroconf/_protocol/outgoing.py
@@ -24,8 +24,9 @@ from __future__ import annotations
 
 import enum
 import logging
+from collections.abc import Sequence
 from struct import Struct
-from typing import TYPE_CHECKING, Sequence
+from typing import TYPE_CHECKING
 
 from .._dns import DNSPointer, DNSQuestion, DNSRecord
 from .._exceptions import NamePartTooLongException
@@ -271,7 +272,7 @@ class DNSOutgoing:
         """
 
         # split name into each label
-        if name.endswith("."):
+        if name and name[-1] == ".":
             name = name[:-1]
 
         index = self.names.get(name, 0)
diff --git a/src/zeroconf/_record_update.py b/src/zeroconf/_record_update.py
index 5f817511363d41155ba398feeef32f02cadee50e..497ee39df141af1a6a404058ee225470251b6f89 100644
--- a/src/zeroconf/_record_update.py
+++ b/src/zeroconf/_record_update.py
@@ -43,6 +43,6 @@ class RecordUpdate:
         """Get the new or old record."""
         if index == 0:
             return self.new
-        elif index == 1:
+        if index == 1:
             return self.old
         raise IndexError(index)
diff --git a/src/zeroconf/_services/__init__.py b/src/zeroconf/_services/__init__.py
index 6936aed61cf09d0f217be41227a7225196d5c01c..b244552f1b38fd6362c9a237c56fcc4d4f0e16b5 100644
--- a/src/zeroconf/_services/__init__.py
+++ b/src/zeroconf/_services/__init__.py
@@ -38,13 +38,13 @@ class ServiceStateChange(enum.Enum):
 
 class ServiceListener:
     def add_service(self, zc: Zeroconf, type_: str, name: str) -> None:
-        raise NotImplementedError()
+        raise NotImplementedError
 
     def remove_service(self, zc: Zeroconf, type_: str, name: str) -> None:
-        raise NotImplementedError()
+        raise NotImplementedError
 
     def update_service(self, zc: Zeroconf, type_: str, name: str) -> None:
-        raise NotImplementedError()
+        raise NotImplementedError
 
 
 class Signal:
diff --git a/src/zeroconf/_services/browser.py b/src/zeroconf/_services/browser.py
index c2ab115b0a1c00a486c225becd111e823f8266f5..ab8c050d9d53bdf7e2de3463dbced7d2564797dc 100644
--- a/src/zeroconf/_services/browser.py
+++ b/src/zeroconf/_services/browser.py
@@ -29,16 +29,13 @@ import random
 import threading
 import time
 import warnings
+from collections.abc import Iterable
 from functools import partial
 from types import TracebackType  # used in type hints
 from typing import (
     TYPE_CHECKING,
     Any,
     Callable,
-    Dict,
-    Iterable,
-    List,
-    Set,
     cast,
 )
 
@@ -96,7 +93,7 @@ int_ = int
 bool_ = bool
 str_ = str
 
-_QuestionWithKnownAnswers = Dict[DNSQuestion, Set[DNSPointer]]
+_QuestionWithKnownAnswers = dict[DNSQuestion, set[DNSPointer]]
 
 heappop = heapq.heappop
 heappush = heapq.heappush
@@ -282,7 +279,7 @@ def generate_service_query(
             log.debug("Asking %s was suppressed by the question history", question)
             continue
         if TYPE_CHECKING:
-            pointer_known_answers = cast(Set[DNSPointer], known_answers)
+            pointer_known_answers = cast(set[DNSPointer], known_answers)
         else:
             pointer_known_answers = known_answers
         questions_with_known_answers[question] = pointer_known_answers
@@ -618,10 +615,10 @@ class _ServiceBrowserBase(RecordUpdateListener):
         self._query_sender_task: asyncio.Task | None = None
 
         if hasattr(handlers, "add_service"):
-            listener = cast("ServiceListener", handlers)
+            listener = cast(ServiceListener, handlers)
             handlers = None
 
-        handlers = cast(List[Callable[..., None]], handlers or [])
+        handlers = cast(list[Callable[..., None]], handlers or [])
 
         if listener:
             handlers.append(_service_state_changed_from_listener(listener))
diff --git a/src/zeroconf/_services/info.py b/src/zeroconf/_services/info.py
index 67777459403eb52737bb80cd32872b0dd5dadcad..9cd8df163fc0b2155181526c512852eca8d2fcd6 100644
--- a/src/zeroconf/_services/info.py
+++ b/src/zeroconf/_services/info.py
@@ -24,7 +24,7 @@ from __future__ import annotations
 
 import asyncio
 import random
-from typing import TYPE_CHECKING, Dict, List, Optional, cast
+from typing import TYPE_CHECKING, cast
 
 from .._cache import DNSCache
 from .._dns import (
@@ -378,13 +378,13 @@ class ServiceInfo(RecordUpdateListener):
         result = b""
         for key, value in properties.items():
             if isinstance(key, str):
-                key = key.encode("utf-8")
+                key = key.encode("utf-8")  # noqa: PLW2901
                 properties_contain_str = True
 
             record = key
             if value is not None:
                 if not isinstance(value, bytes):
-                    value = str(value).encode("utf-8")
+                    value = str(value).encode("utf-8")  # noqa: PLW2901
                     properties_contain_str = True
                 record += b"=" + value
             list_.append(record)
@@ -395,7 +395,7 @@ class ServiceInfo(RecordUpdateListener):
             # as-is, without decoding them, otherwise calling
             # self.properties will lazy decode them, which is expensive.
             if TYPE_CHECKING:
-                self._properties = cast("Dict[bytes, Optional[bytes]]", properties)
+                self._properties = cast(dict[bytes, bytes | None], properties)
             else:
                 self._properties = properties
         self.text = result
@@ -462,7 +462,7 @@ class ServiceInfo(RecordUpdateListener):
         """Set IPv6 addresses from the cache."""
         if TYPE_CHECKING:
             self._ipv6_addresses = cast(
-                "List[ZeroconfIPv6Address]",
+                list[ZeroconfIPv6Address],
                 self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_AAAA),
             )
         else:
@@ -472,7 +472,7 @@ class ServiceInfo(RecordUpdateListener):
         """Set IPv4 addresses from the cache."""
         if TYPE_CHECKING:
             self._ipv4_addresses = cast(
-                "List[ZeroconfIPv4Address]",
+                list[ZeroconfIPv4Address],
                 self._get_ip_addresses_from_cache_lifo(zc, now, _TYPE_A),
             )
         else:
@@ -524,7 +524,7 @@ class ServiceInfo(RecordUpdateListener):
                 # since by default IPv4Address.__eq__ compares the
                 # the addresses on version and int which more than
                 # we need here since we know the version is 4.
-                elif ip_addr.zc_integer != ipv4_addresses[0].zc_integer:
+                if ip_addr.zc_integer != ipv4_addresses[0].zc_integer:
                     ipv4_addresses.remove(ip_addr)
                     ipv4_addresses.insert(0, ip_addr)
 
@@ -540,7 +540,7 @@ class ServiceInfo(RecordUpdateListener):
             # since by default IPv6Address.__eq__ compares the
             # the addresses on version and int which more than
             # we need here since we know the version is 6.
-            elif ip_addr.zc_integer != self._ipv6_addresses[0].zc_integer:
+            if ip_addr.zc_integer != self._ipv6_addresses[0].zc_integer:
                 ipv6_addresses.remove(ip_addr)
                 ipv6_addresses.insert(0, ip_addr)
 
@@ -724,7 +724,7 @@ class ServiceInfo(RecordUpdateListener):
         cache = zc.cache
         if TYPE_CHECKING:
             records = cast(
-                "List[DNSAddress]",
+                list[DNSAddress],
                 cache.get_all_by_details(self.server_key, _type, _CLASS_IN),
             )
         else:
diff --git a/src/zeroconf/_utils/asyncio.py b/src/zeroconf/_utils/asyncio.py
index c92d99d5624e66cf5c2264691c849fb9116af39a..8609060179b352403dea4a2af46f53d9a3b509bf 100644
--- a/src/zeroconf/_utils/asyncio.py
+++ b/src/zeroconf/_utils/asyncio.py
@@ -26,7 +26,8 @@ import asyncio
 import concurrent.futures
 import contextlib
 import sys
-from typing import Any, Awaitable, Coroutine
+from collections.abc import Awaitable, Coroutine
+from typing import Any
 
 from .._exceptions import EventLoopBlocked
 from ..const import _LOADED_SYSTEM_TIMEOUT
diff --git a/src/zeroconf/_utils/net.py b/src/zeroconf/_utils/net.py
index 3cc4336bf88ffa91fda607e3f36b7e2c7f4dc935..c2312e01fc81195f131459152f16a12e4d911b8f 100644
--- a/src/zeroconf/_utils/net.py
+++ b/src/zeroconf/_utils/net.py
@@ -28,7 +28,8 @@ import ipaddress
 import socket
 import struct
 import sys
-from typing import Any, Sequence, Tuple, Union, cast
+from collections.abc import Sequence
+from typing import Any, Union, cast
 
 import ifaddr
 
@@ -42,7 +43,7 @@ class InterfaceChoice(enum.Enum):
     All = 2
 
 
-InterfacesType = Union[Sequence[Union[str, int, Tuple[Tuple[str, int, int], int]]], InterfaceChoice]
+InterfacesType = Union[Sequence[Union[str, int, tuple[tuple[str, int, int], int]]], InterfaceChoice]
 
 
 @enum.unique
@@ -73,40 +74,41 @@ def _encode_address(address: str) -> bytes:
 
 
 def get_all_addresses() -> list[str]:
-    return list({addr.ip for iface in ifaddr.get_adapters() for addr in iface.ips if addr.is_IPv4})
+    return list({addr.ip for iface in ifaddr.get_adapters() for addr in iface.ips if addr.is_IPv4})  # type: ignore[misc]
 
 
 def get_all_addresses_v6() -> list[tuple[tuple[str, int, int], int]]:
     # IPv6 multicast uses positive indexes for interfaces
     # TODO: What about multi-address interfaces?
     return list(
-        {(addr.ip, iface.index) for iface in ifaddr.get_adapters() for addr in iface.ips if addr.is_IPv6}
+        {(addr.ip, iface.index) for iface in ifaddr.get_adapters() for addr in iface.ips if addr.is_IPv6}  # type: ignore[misc]
     )
 
 
-def ip6_to_address_and_index(adapters: list[Any], ip: str) -> tuple[tuple[str, int, int], int]:
+def ip6_to_address_and_index(adapters: list[ifaddr.Adapter], ip: str) -> tuple[tuple[str, int, int], int]:
     if "%" in ip:
         ip = ip[: ip.index("%")]  # Strip scope_id.
     ipaddr = ipaddress.ip_address(ip)
     for adapter in adapters:
         for adapter_ip in adapter.ips:
             # IPv6 addresses are represented as tuples
-            if isinstance(adapter_ip.ip, tuple) and ipaddress.ip_address(adapter_ip.ip[0]) == ipaddr:
-                return (
-                    cast(Tuple[str, int, int], adapter_ip.ip),
-                    cast(int, adapter.index),
-                )
+            if (
+                adapter.index is not None
+                and isinstance(adapter_ip.ip, tuple)
+                and ipaddress.ip_address(adapter_ip.ip[0]) == ipaddr
+            ):
+                return (adapter_ip.ip, adapter.index)
 
     raise RuntimeError(f"No adapter found for IP address {ip}")
 
 
-def interface_index_to_ip6_address(adapters: list[Any], index: int) -> tuple[str, int, int]:
+def interface_index_to_ip6_address(adapters: list[ifaddr.Adapter], index: int) -> tuple[str, int, int]:
     for adapter in adapters:
         if adapter.index == index:
             for adapter_ip in adapter.ips:
                 # IPv6 addresses are represented as tuples
                 if isinstance(adapter_ip.ip, tuple):
-                    return cast(Tuple[str, int, int], adapter_ip.ip)
+                    return adapter_ip.ip
 
     raise RuntimeError(f"No adapter found for index {index}")
 
@@ -126,9 +128,9 @@ def ip6_addresses_to_indexes(
 
     for iface in interfaces:
         if isinstance(iface, int):
-            result.append((interface_index_to_ip6_address(adapters, iface), iface))
+            result.append((interface_index_to_ip6_address(adapters, iface), iface))  # type: ignore[arg-type]
         elif isinstance(iface, str) and ipaddress.ip_address(iface).version == 6:
-            result.append(ip6_to_address_and_index(adapters, iface))
+            result.append(ip6_to_address_and_index(adapters, iface))  # type: ignore[arg-type]
 
     return result
 
@@ -260,6 +262,25 @@ def new_socket(
                 bind_tup,
             )
             return None
+        if ex.errno == errno.EADDRINUSE:
+            if sys.platform.startswith("darwin") or sys.platform.startswith("freebsd"):
+                log.error(
+                    "Address in use when binding to %s; "
+                    "On BSD based systems sharing the same port with another "
+                    "stack may require processes to run with the same UID; "
+                    "When using avahi, make sure disallow-other-stacks is set"
+                    " to no in avahi-daemon.conf",
+                    bind_tup,
+                )
+            else:
+                log.error(
+                    "Address in use when binding to %s; "
+                    "When using avahi, make sure disallow-other-stacks is set"
+                    " to no in avahi-daemon.conf",
+                    bind_tup,
+                )
+            # This is still a fatal error as its not going to work
+            # if we can't hear the traffic coming in.
         raise
     log.debug("Created socket %s", s)
     return s
@@ -301,6 +322,20 @@ def add_multicast_member(
                 interface,
             )
             return False
+        if _errno == errno.ENOBUFS:
+            # https://github.com/python-zeroconf/python-zeroconf/issues/1510
+            if not is_v6 and sys.platform.startswith("linux"):
+                log.warning(
+                    "No buffer space available when adding %s to multicast group, "
+                    "try increasing `net.ipv4.igmp_max_memberships` to `1024` in sysctl.conf",
+                    interface,
+                )
+            else:
+                log.warning(
+                    "No buffer space available when adding %s to multicast group.",
+                    interface,
+                )
+            return False
         if _errno == errno.EADDRNOTAVAIL:
             log.info(
                 "Address not available when adding %s to multicast "
@@ -340,7 +375,7 @@ def new_respond_socket(
     respond_socket = new_socket(
         ip_version=(IPVersion.V6Only if is_v6 else IPVersion.V4Only),
         apple_p2p=apple_p2p,
-        bind_addr=cast(Tuple[Tuple[str, int, int], int], interface)[0] if is_v6 else (cast(str, interface),),
+        bind_addr=cast(tuple[tuple[str, int, int], int], interface)[0] if is_v6 else (cast(str, interface),),
     )
     if not respond_socket:
         return None
@@ -399,8 +434,7 @@ def create_sockets(
     return listen_socket, respond_sockets
 
 
-def get_errno(e: Exception) -> int:
-    assert isinstance(e, socket.error)
+def get_errno(e: OSError) -> int:
     return cast(int, e.args[0])
 
 
diff --git a/src/zeroconf/asyncio.py b/src/zeroconf/asyncio.py
index ce5a43eb9a16d3e4f7ed5ca82c4d7daddc0c67ba..a0f4a99db150bff68ccfd48e9ff0191674fed83d 100644
--- a/src/zeroconf/asyncio.py
+++ b/src/zeroconf/asyncio.py
@@ -24,8 +24,9 @@ from __future__ import annotations
 
 import asyncio
 import contextlib
+from collections.abc import Awaitable
 from types import TracebackType  # used in type hints
-from typing import Awaitable, Callable
+from typing import Callable
 
 from ._core import Zeroconf
 from ._dns import DNSQuestionType
diff --git a/tests/conftest.py b/tests/conftest.py
index 1f323785c2410ec333e532c449a6fcfdcb3b3422..531c810befc48ad4d83ddafeb49c84094559c332 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -23,9 +23,11 @@ def verify_threads_ended():
 @pytest.fixture
 def run_isolated():
     """Change the mDNS port to run the test in isolation."""
-    with patch.object(query_handler, "_MDNS_PORT", 5454), patch.object(
-        _core, "_MDNS_PORT", 5454
-    ), patch.object(const, "_MDNS_PORT", 5454):
+    with (
+        patch.object(query_handler, "_MDNS_PORT", 5454),
+        patch.object(_core, "_MDNS_PORT", 5454),
+        patch.object(const, "_MDNS_PORT", 5454),
+    ):
         yield
 
 
diff --git a/tests/test_handlers.py b/tests/test_handlers.py
index fd0e689c46f9fabb77239e7063e4c02d20c9155e..ffa4ff88cfcef796f12c255fe5d8165d834705b4 100644
--- a/tests/test_handlers.py
+++ b/tests/test_handlers.py
@@ -67,10 +67,9 @@ class TestRegistrar(unittest.TestCase):
         def get_ttl(record_type):
             if expected_ttl is not None:
                 return expected_ttl
-            elif record_type in [const._TYPE_A, const._TYPE_SRV, const._TYPE_NSEC]:
+            if record_type in [const._TYPE_A, const._TYPE_SRV, const._TYPE_NSEC]:
                 return const._DNS_HOST_TTL
-            else:
-                return const._DNS_OTHER_TTL
+            return const._DNS_OTHER_TTL
 
         def _process_outgoing_packet(out):
             """Sends an outgoing packet."""
diff --git a/tests/test_history.py b/tests/test_history.py
index 4c9836ce6285ac285a0bae65542d7962e1d91b4d..e9254168e1d29c9a62d17c78bbf91df5cfbb1586 100644
--- a/tests/test_history.py
+++ b/tests/test_history.py
@@ -3,7 +3,7 @@
 from __future__ import annotations
 
 import zeroconf as r
-import zeroconf.const as const
+from zeroconf import const
 from zeroconf._history import QuestionHistory
 
 
diff --git a/tests/test_init.py b/tests/test_init.py
index a36ff8fd286e1f4d0e317a1b8e75ab198aa08593..5ccb9ef634a7663d245ce1d9e71334c98e86c39b 100644
--- a/tests/test_init.py
+++ b/tests/test_init.py
@@ -89,9 +89,10 @@ class Names(unittest.TestCase):
         # instantiate a zeroconf instance
         zc = Zeroconf(interfaces=["127.0.0.1"])
 
-        with patch("zeroconf._logger.log.warning") as mocked_log_warn, patch(
-            "zeroconf._logger.log.debug"
-        ) as mocked_log_debug:
+        with (
+            patch("zeroconf._logger.log.warning") as mocked_log_warn,
+            patch("zeroconf._logger.log.debug") as mocked_log_debug,
+        ):
             # now that we have a long packet in our possession, let's verify the
             # exception handling.
             out = r.DNSOutgoing(const._FLAGS_QR_RESPONSE | const._FLAGS_AA)
diff --git a/tests/test_listener.py b/tests/test_listener.py
index a55fc14352e550769bd536e0118e90d7599a212f..4897eabe0a6a45588cc875ef75d7023ec800873c 100644
--- a/tests/test_listener.py
+++ b/tests/test_listener.py
@@ -59,8 +59,9 @@ def test_guard_against_oversized_packets():
 
     try:
         # We are patching to generate an oversized packet
-        with patch.object(outgoing, "_MAX_MSG_ABSOLUTE", 100000), patch.object(
-            outgoing, "_MAX_MSG_TYPICAL", 100000
+        with (
+            patch.object(outgoing, "_MAX_MSG_ABSOLUTE", 100000),
+            patch.object(outgoing, "_MAX_MSG_TYPICAL", 100000),
         ):
             over_sized_packet = generated.packets()[0]
             assert len(over_sized_packet) > const._MAX_MSG_ABSOLUTE
diff --git a/tests/test_logger.py b/tests/test_logger.py
index aa5b5382b0de6ac352040eb477abe7ff224d13e7..4e09aa3b1f3636c34941bddca26e1f0dc3d39132 100644
--- a/tests/test_logger.py
+++ b/tests/test_logger.py
@@ -27,17 +27,19 @@ def test_log_warning_once():
     """Test we only log with warning level once."""
     QuietLogger._seen_logs = {}
     quiet_logger = QuietLogger()
-    with patch("zeroconf._logger.log.warning") as mock_log_warning, patch(
-        "zeroconf._logger.log.debug"
-    ) as mock_log_debug:
+    with (
+        patch("zeroconf._logger.log.warning") as mock_log_warning,
+        patch("zeroconf._logger.log.debug") as mock_log_debug,
+    ):
         quiet_logger.log_warning_once("the warning")
 
     assert mock_log_warning.mock_calls
     assert not mock_log_debug.mock_calls
 
-    with patch("zeroconf._logger.log.warning") as mock_log_warning, patch(
-        "zeroconf._logger.log.debug"
-    ) as mock_log_debug:
+    with (
+        patch("zeroconf._logger.log.warning") as mock_log_warning,
+        patch("zeroconf._logger.log.debug") as mock_log_debug,
+    ):
         quiet_logger.log_warning_once("the warning")
 
     assert not mock_log_warning.mock_calls
@@ -48,17 +50,19 @@ def test_log_exception_warning():
     """Test we only log with warning level once."""
     QuietLogger._seen_logs = {}
     quiet_logger = QuietLogger()
-    with patch("zeroconf._logger.log.warning") as mock_log_warning, patch(
-        "zeroconf._logger.log.debug"
-    ) as mock_log_debug:
+    with (
+        patch("zeroconf._logger.log.warning") as mock_log_warning,
+        patch("zeroconf._logger.log.debug") as mock_log_debug,
+    ):
         quiet_logger.log_exception_warning("the exception warning")
 
     assert mock_log_warning.mock_calls
     assert not mock_log_debug.mock_calls
 
-    with patch("zeroconf._logger.log.warning") as mock_log_warning, patch(
-        "zeroconf._logger.log.debug"
-    ) as mock_log_debug:
+    with (
+        patch("zeroconf._logger.log.warning") as mock_log_warning,
+        patch("zeroconf._logger.log.debug") as mock_log_debug,
+    ):
         quiet_logger.log_exception_warning("the exception warning")
 
     assert not mock_log_warning.mock_calls
@@ -85,17 +89,19 @@ def test_log_exception_once():
     QuietLogger._seen_logs = {}
     quiet_logger = QuietLogger()
     exc = Exception()
-    with patch("zeroconf._logger.log.warning") as mock_log_warning, patch(
-        "zeroconf._logger.log.debug"
-    ) as mock_log_debug:
+    with (
+        patch("zeroconf._logger.log.warning") as mock_log_warning,
+        patch("zeroconf._logger.log.debug") as mock_log_debug,
+    ):
         quiet_logger.log_exception_once(exc, "the exceptional exception warning")
 
     assert mock_log_warning.mock_calls
     assert not mock_log_debug.mock_calls
 
-    with patch("zeroconf._logger.log.warning") as mock_log_warning, patch(
-        "zeroconf._logger.log.debug"
-    ) as mock_log_debug:
+    with (
+        patch("zeroconf._logger.log.warning") as mock_log_warning,
+        patch("zeroconf._logger.log.debug") as mock_log_debug,
+    ):
         quiet_logger.log_exception_once(exc, "the exceptional exception warning")
 
     assert not mock_log_warning.mock_calls
diff --git a/tests/test_services.py b/tests/test_services.py
index e93174cc72e7f3e36309830e91464f8e74e83cf8..7d7c3fc7d79968ba53369de057d4f829ed007c6b 100644
--- a/tests/test_services.py
+++ b/tests/test_services.py
@@ -71,7 +71,6 @@ class ListenerTest(unittest.TestCase):
         class MySubListener(r.ServiceListener):
             def add_service(self, zeroconf, type, name):
                 sub_service_added.set()
-                pass
 
             def remove_service(self, zeroconf, type, name):
                 pass
diff --git a/tests/utils/test_net.py b/tests/utils/test_net.py
index 489a6460c6c2fbf477fa3f9cc940399dbc1cb5d5..f763b655c22598250b546292c2bea3a58cc92a2b 100644
--- a/tests/utils/test_net.py
+++ b/tests/utils/test_net.py
@@ -4,6 +4,7 @@ from __future__ import annotations
 
 import errno
 import socket
+import sys
 import unittest
 from unittest.mock import MagicMock, Mock, patch
 
@@ -82,9 +83,11 @@ def test_ip6_addresses_to_indexes():
 
 def test_normalize_interface_choice_errors():
     """Test we generate exception on invalid input."""
-    with patch("zeroconf._utils.net.get_all_addresses", return_value=[]), patch(
-        "zeroconf._utils.net.get_all_addresses_v6", return_value=[]
-    ), pytest.raises(RuntimeError):
+    with (
+        patch("zeroconf._utils.net.get_all_addresses", return_value=[]),
+        patch("zeroconf._utils.net.get_all_addresses_v6", return_value=[]),
+        pytest.raises(RuntimeError),
+    ):
         netutils.normalize_interface_choice(r.InterfaceChoice.All)
 
     with pytest.raises(TypeError):
@@ -128,8 +131,10 @@ def test_disable_ipv6_only_or_raise():
         errors_logged.append(args)
 
     sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-    with pytest.raises(OSError), patch.object(netutils.log, "error", _log_error), patch(
-        "socket.socket.setsockopt", side_effect=OSError
+    with (
+        pytest.raises(OSError),
+        patch.object(netutils.log, "error", _log_error),
+        patch("socket.socket.setsockopt", side_effect=OSError),
     ):
         netutils.disable_ipv6_only_or_raise(sock)
 
@@ -177,7 +182,7 @@ def test_set_mdns_port_socket_options_for_ip_version():
         netutils.set_mdns_port_socket_options_for_ip_version(sock, ("",), r.IPVersion.V4Only)
 
 
-def test_add_multicast_member():
+def test_add_multicast_member(caplog: pytest.LogCaptureFixture) -> None:
     sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
     interface = "127.0.0.1"
 
@@ -217,6 +222,26 @@ def test_add_multicast_member():
     with patch("socket.socket.setsockopt"):
         assert netutils.add_multicast_member(sock, interface) is True
 
+    # Ran out of IGMP memberships is forgiving and logs about igmp_max_memberships on linux
+    caplog.clear()
+    with (
+        patch.object(sys, "platform", "linux"),
+        patch("socket.socket.setsockopt", side_effect=OSError(errno.ENOBUFS, "No buffer space available")),
+    ):
+        assert netutils.add_multicast_member(sock, interface) is False
+        assert "No buffer space available" in caplog.text
+        assert "net.ipv4.igmp_max_memberships" in caplog.text
+
+    # Ran out of IGMP memberships is forgiving and logs
+    caplog.clear()
+    with (
+        patch.object(sys, "platform", "darwin"),
+        patch("socket.socket.setsockopt", side_effect=OSError(errno.ENOBUFS, "No buffer space available")),
+    ):
+        assert netutils.add_multicast_member(sock, interface) is False
+        assert "No buffer space available" in caplog.text
+        assert "net.ipv4.igmp_max_memberships" not in caplog.text
+
 
 def test_bind_raises_skips_address():
     """Test bind failing in new_socket returns None on EADDRNOTAVAIL."""
@@ -235,6 +260,40 @@ def test_bind_raises_skips_address():
         netutils.new_socket(("0.0.0.0", 0))  # type: ignore[arg-type]
 
 
+def test_bind_raises_address_in_use(caplog: pytest.LogCaptureFixture) -> None:
+    """Test bind failing in new_socket returns None on EADDRINUSE."""
+
+    def _mock_socket(*args, **kwargs):
+        sock = MagicMock()
+        sock.bind = MagicMock(side_effect=OSError(errno.EADDRINUSE, f"Error: {errno.EADDRINUSE}"))
+        return sock
+
+    with (
+        pytest.raises(OSError),
+        patch.object(sys, "platform", "darwin"),
+        patch("socket.socket", _mock_socket),
+    ):
+        netutils.new_socket(("0.0.0.0", 0))  # type: ignore[arg-type]
+    assert (
+        "On BSD based systems sharing the same port with "
+        "another stack may require processes to run with the same UID"
+    ) in caplog.text
+    assert (
+        "When using avahi, make sure disallow-other-stacks is set to no in avahi-daemon.conf" in caplog.text
+    )
+
+    caplog.clear()
+    with pytest.raises(OSError), patch.object(sys, "platform", "linux"), patch("socket.socket", _mock_socket):
+        netutils.new_socket(("0.0.0.0", 0))  # type: ignore[arg-type]
+    assert (
+        "On BSD based systems sharing the same port with "
+        "another stack may require processes to run with the same UID"
+    ) not in caplog.text
+    assert (
+        "When using avahi, make sure disallow-other-stacks is set to no in avahi-daemon.conf" in caplog.text
+    )
+
+
 def test_new_respond_socket_new_socket_returns_none():
     """Test new_respond_socket returns None if new_socket returns None."""
     with patch.object(netutils, "new_socket", return_value=None):