Skip to content

OLED: IndexError when oled_network_interface="all" and interface count changes between updates #4

@jesus33lcc

Description

@jesus33lcc

Versions

  • pm_auto: 1.2.12
  • pironman5: 1.2.22 (parent service)
  • Raspberry Pi 5 (16 GB), Debian Trixie, Python 3.13

Symptom

With default oled_network_interface: "all", on a host where the set of
network interfaces changes frequently (e.g. Docker bridges coming up and
down when stacks are recreated), the OLED render loop raises
IndexError: list index out of range once per second:

File "/.../pm_auto/oled.py", line 172, in draw_oled
    ip = ips[self.ip_index]
         ~~~^^^^^^^^^^^^^^^
IndexError: list index out of range

The service stays alive (the @log_error decorator swallows the
exception), but the journal fills with tracebacks and the OLED frame
that renders the IP stops updating.

Root cause

In draw_oled, after rendering one frame, the index is bumped:

self.ip_index = (self.ip_index + 1) % len(ips)

…using len(ips) as it was during this call. On the next call,
get_data may return a shorter data['ips'] (an interface disappeared
between calls), so self.ip_index can be >= len(ips). The subsequent
ips[self.ip_index] then raises.

This is easy to trigger on a host with many short-lived bridges
(typical Docker setup with several compose stacks).

Reproduction

  1. oled_network_interface: "all" (default).
  2. On the host, repeatedly recreate Docker stacks so the bridge count
    fluctuates (e.g. docker compose down && up -d on a few stacks).
  3. journalctl -u pironman5 -f shows the traceback every 1 s.

Suggested fix

Clamp self.ip_index against the current list size before indexing:

ips = data['ips']
ip = 'DISCONNECTED'

if len(ips) > 0:
    if self.ip_index >= len(ips):
        self.ip_index = 0
    ip = ips[self.ip_index]
    if time.time() - self.ip_show_next_timestamp > self.ip_show_next_interval:
        self.ip_show_next_timestamp = time.time()
        self.ip_index = (self.ip_index + 1) % len(ips)

Workaround

Setting oled_network_interface to a specific, stable interface
("eth0" in my case) sidesteps the issue.

Related

#2 (filtering out virtual interface prefixes) would reduce how often
the list size changes, but doesn't fully prevent the crash: any
transient interface that isn't in the prefix list (or any future
interface change) would still trigger the same IndexError. The two
fixes are complementary.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions