Skip to content

FREEBOX plugin can generate false Disconnected/Flapping state when L3 reachability temporarily drops #1828

Description

@Svestis

What installation are you running?

Production (netalertx) 📦

Is there an existing issue for this?

The issue occurs in the following browsers. Select at least 2.

  • Firefox
  • Chrome
  • Edge
  • Safari (unsupported) - PRs welcome
  • N/A - This is an issue with the backend

Current Behavior

The FREEBOX plugin can report a device as disconnected even while the Freebox API still reports the host as active and physically connected.

I observed this with a Freebox TV Player connected via Ethernet. The device repeatedly transitions between Connected and Disconnected in NetAlertX, which eventually causes the logical parent device to be shown as Flapping.

Investigation showed that the FREEBOX plugin only emits a host when at least one of its L3 addresses has reachable=true:

for ip in [ip for ip in host["l3connectivities"] if ip.get("reachable")]:

During a captured false-disconnection cycle, the Freebox API still reported the Ethernet host as active and the physical Ethernet link as up, while its L3 addresses temporarily had reachable=false.

The relevant state was equivalent to:

host.active = true
host.reachable = false

Ethernet:
  link = up

IPv4:
  active = true
  reachable = false

IPv6 link-local:
  active = true
  reachable = false

IPv6 global:
  active = false
  reachable = false

Because none of the L3 addresses had reachable=true, the FREEBOX plugin emitted no scan entry for this MAC during that cycle.

In the same processing cycle, the device was also absent from the ICMP scan. NetAlertX therefore had no presence entry for the Ethernet NIC in CurrentScan and generated a Disconnected event.

The logical Freebox TV Player uses this Ethernet device as a NIC, so it received a Disconnected event at the same time. When an L3 address later became reachable again, FREEBOX emitted the NIC again and both devices transitioned back to Connected.

This repeated several times:

Connected
Disconnected
Connected
Disconnected
Connected

causing the logical device to be classified as Flapping.

The Freebox API documentation distinguishes these states:

  • LanHost.active: the host sends traffic to the Freebox
  • LanHost.reachable: the host can receive traffic from the Freebox
  • LanHostL3Connectivity.active: the L3 connection is active
  • LanHostL3Connectivity.reachable: the L3 connection is reachable

Therefore an L3 connection temporarily having reachable=false does not necessarily mean that the host itself is disconnected.

Expected Behavior

A Freebox host that remains connected should not generate false Disconnected / Connected transitions solely because all of its L3 addresses temporarily report reachable=false.

The FREEBOX plugin should distinguish host/device presence from temporary L3 reachability so that a host which the Freebox still reports as connected/active does not disappear from the scan solely because none of its individual IP addresses are currently marked reachable.

The exact presence criteria are an implementation decision, since the Freebox API exposes several relevant signals (LanHost.active, LanHost.reachable, L3 active/reachable, and connection-specific information).

The expected outcome is that temporary L3 reachability changes do not incorrectly cause an otherwise connected device, or a logical device derived from its NIC presence, to transition to Disconnected and eventually Flapping.

Steps To Reproduce

  1. Enable the FREEBOX plugin and configure it to scan a Freebox using the LAN Browser API.

  2. Have a device connected to the Freebox for which the API can temporarily report:

    • LanHost.active = true
    • at least one LanHostL3Connectivity.active = true
    • all LanHostL3Connectivity.reachable = false

    In the observed case this was an Ethernet-connected Freebox TV Player whose physical Ethernet link also remained up.

  3. Allow the scheduled FREEBOX scan to run while all of the host's L3 addresses have reachable=false.

  4. Observe that the FREEBOX plugin produces no result for that host because it only processes L3 connections satisfying:

    if ip.get("reachable")
  5. If no other scanner detects the device during the same processing cycle, observe that NetAlertX generates a Disconnected event for the device.

  6. When one or more L3 addresses later become reachable=true, allow another FREEBOX scan to run and observe that the device is emitted again and transitions back to Connected.

  7. If this L3 reachability state changes repeatedly, observe repeated Connected / Disconnected events and eventually a Flapping status.

When the device is configured as a NIC of a logical device, the logical parent follows the same presence transitions and can also become Flapping.

Relevant app.conf settings

FREEBOX_RUN = 'schedule'
FREEBOX_RUN_SCHD = '*/5 * * * *'
FREEBOX_address = 'mafreebox.freebox.fr'
FREEBOX_api_version = 6
FREEBOX_api_port = 443
FREEBOX_RUN_TIMEOUT = 30
FREEBOX_SET_ALWAYS = ['devMac', 'devLastIP', 'devName']
FREEBOX_SET_EMPTY = []

docker-compose.yml

services:
  netalertx:
    image: ghcr.io/netalertx/netalertx:latest
    container_name: netalertx
    restart: unless-stopped

    network_mode: host

    volumes:
      - /opt/homelab/data/netalertx:/data

    tmpfs:
      - "/tmp:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime"

    cap_drop:
      - ALL

    cap_add:
      - NET_ADMIN
      - NET_RAW
      - NET_BIND_SERVICE
      - CHOWN
      - SETUID
      - SETGID

    read_only: true

    security_opt:
      - no-new-privileges:true

    environment:
      - TZ=Europe/Paris

    deploy:
      resources:
        reservations:
          memory: 1G
        limits:
          memory: 2G

Debug or Trace enabled

  • I have read and followed the steps in the wiki link above and provided the required debug logs and the log section covers the time when the issue occurs.

Relevant app.log section

The relevant scan cycle is shown below. MAC addresses and IP addresses have been anonymized.

21:21:00 [Scheduler] run for FREEBOX: YES
21:21:00 [Plugins] SUCCESS for FREEBOX received 26 entries
21:21:00 [Plugins] Mapping objects to database table: CurrentScan

# The affected Ethernet NIC is absent from the FREEBOX mapping.

21:23:01 [ICMP] TIMEOUT - process terminated
21:23:02 [ICMP] Script finished - 11 added or updated
21:23:02 [Plugins] SUCCESS for ICMP received 11 entries
21:23:02 [Plugins] Mapping objects to database table: CurrentScan

# The affected Ethernet NIC is also absent from the ICMP mapping.

21:23:02 [MAIN] processScan: True
21:23:02 [MAIN] start processing scan results
21:23:02 [Process Scan] Processing scan results
21:23:02 [Scan Stats] Devices Detected.......: 39
21:23:02 [Scan Stats] New Devices............: 0
21:23:02 [Scan Stats] Down Alerts............: 1
21:23:02 [Scan Stats] New Down Alerts........: 0
21:23:02 [Scan Stats] New Connections........: 13
21:23:02 [Scan Stats] Disconnections.........: 2
21:23:02 [Scan Stats] IP Changes.............: 6
21:23:02     FREEBOX: 26
21:23:02     ICMP: 11

The two Disconnected events generated by this cycle were the affected Ethernet NIC and its logical parent:

2026-10-01 19:23:02  Disconnected  <ETHERNET_NIC_MAC>  <IP_ADDRESS>
2026-10-01 19:23:02  Disconnected  <LOGICAL_PARENT_MAC>  0.0.0.0

The preceding and following events show both devices transitioning together:

2026-10-01 19:17:47  Connected     <ETHERNET_NIC_MAC>
2026-10-01 19:17:47  Connected     <LOGICAL_PARENT_MAC>

2026-10-01 19:23:02  Disconnected  <ETHERNET_NIC_MAC>
2026-10-01 19:23:02  Disconnected  <LOGICAL_PARENT_MAC>

2026-10-01 19:27:33  Connected     <ETHERNET_NIC_MAC>
2026-10-01 19:27:33  Connected     <LOGICAL_PARENT_MAC>

2026-10-01 19:33:01  Disconnected  <ETHERNET_NIC_MAC>
2026-10-01 19:33:01  Disconnected  <LOGICAL_PARENT_MAC>

2026-10-01 19:37:21  Connected     <ETHERNET_NIC_MAC>
2026-10-01 19:37:21  Connected     <LOGICAL_PARENT_MAC>

During the failing FREEBOX cycle, the raw Freebox API data for the affected Ethernet host showed that the host was still active and its Ethernet link remained up, while all L3 addresses were temporarily reported as unreachable:

host.active = true
host.reachable = false

ethernet_information:
  link = up
  speed = 1000

IPv4:
  active = true
  reachable = false

IPv6 link-local:
  active = true
  reachable = false

IPv6 global:
  active = false
  reachable = false

The FREEBOX plugin currently only emits L3 entries for which reachable is true:

for ip in [ip for ip in host["l3connectivities"] if ip.get("reachable")]:

As a result, this host produced no FREEBOX scan entry during that cycle despite still being reported as active by the Freebox and having its physical Ethernet link up.

Docker Logs

No additional relevant information was present in the Docker container logs for this issue.

The diagnostic information is emitted to NetAlertX's app.log; the relevant debug-level section from the reproduced scan cycle is included above.

Activity

  1. Svestis commented on Oct 1, 2026

    @Svestis
    ContributorAuthor

    Additional observation: CurrentScan presence during the flapping

    I ran an additional watcher against CurrentScan while investigating the repeated Connected / Disconnected transitions.

    Whenever the affected FREEBOX devices were actually present in CurrentScan, their FREEBOX rows consistently had:

    scanPresence = 1
    

    This was true across IPv4 and IPv6 entries and across multiple FREEBOX scan cycles. The set of L3 entries and their scanLastConnection timestamps changed over time, but I did not observe the FREEBOX plugin inserting the affected device with scanPresence=0.

    This appears consistent with the failure mode described in this issue:

    normal cycle:
    FREEBOX emits MAC + reachable L3 address(es)
        -> CurrentScan contains the MAC with scanPresence=1
    
    failing cycle:
    host remains active / Ethernet link remains up
        -> all L3 addresses have reachable=false
        -> FREEBOX emits no entry for the MAC
        -> MAC is absent from CurrentScan
        -> if another scanner also does not detect it
        -> NetAlertX generates Disconnected
    
    later cycle:
    an L3 address becomes reachable again
        -> FREEBOX emits the MAC again with scanPresence=1
        -> NetAlertX generates Connected
    

    So the observed flapping does not appear to be caused by FREEBOX explicitly reporting the device as absent (scanPresence=0). It is caused by the device disappearing from the FREEBOX results for a scan cycle and then reappearing.

    I also observed that the physical FREEBOX-sourced device and its logical parent transition together. Repeated cycles therefore produce sequences such as:

    Connected
    Disconnected
    Connected
    Disconnected
    Connected
    

    which eventually results in the logical device being classified as Flapping.

    The additional CurrentScan observation therefore seems to support distinguishing device/host presence from L3 address reachability in the FREEBOX plugin, rather than treating the absence of a reachable=true L3 address as equivalent to the host being absent.

    One limitation of this additional capture is that the watcher directly observed the affected devices while they were present in CurrentScan; it does not by itself prove their absence at the exact failing instant. The raw Freebox API and debug-log capture in the original report provide the stronger evidence for that part.

  2. added a commit that references this issue on Oct 2, 2026
    af79016
  3. jokob-sk commented on Oct 2, 2026

    @jokob-sk
    Collaborator

    Thanks for the report.

    This should be available/fixed in the next release.
    It would be great if you could test the ghcr.io/netalertx/netalertx-dev-unsafe Docker image in ~15 minutes (or once the latest GitHub Action finishes).

    ⚠️ Please back up everything first, or ideally spin up a separate container (make sure you use a unique PORT and GRAPHQL_PORT if running instances concurrently) with its own DB and config (a copy of your current setup), as database changes may occur.

    After updating:

    • Click the 🔄 refresh button in the blue header at the top
    • Hard refresh your browser cache (shift + reload) to force js and css files reload

    👉 If I don’t receive confirmation that this works, I may revert the changes to avoid introducing bugs.

    Disclaimer: Running the dev container long-term may lead to data loss, as upgrade paths are not guaranteed.

    Thanks in advance,
    j

  4. added
    Waiting for reply⏳Waiting for the original poster to respond, or discussion in progress.
    next release/in dev image 🚀This is coming in the next release or was already released if the issue is Closed.
    on Oct 2, 2026
  5. added a commit that references this issue on Oct 2, 2026
    067a6a1
  6. Svestis commented on Oct 2, 2026

    @Svestis
    ContributorAuthor

    Hi @jokob-sk ,

    Thanks once again for the quick fix!

    Tested with:

    ghcr.io/netalertx/netalertx-dev-unsafe:sha-067a6a1
    

    I was able to reproduce the exact Freebox API state from the original report twice.

    In both cases, the affected Freebox TV Player Ethernet interface had:

    host.active = True
    
    IPv4:
      active = True
      reachable = False
    
    IPv6 link-local:
      active = True
      reachable = False
    
    All L3 entries:
      reachable = False
    

    First occurrence

    At approximately 21:05, the plugin detected the condition and triggered the new fallback:

    [FREEBOX] Host active but no reachable L3 address - using fallback IP
    

    The affected interface was retained by the FREEBOX scan using its active IPv4 address.

    The subsequent NetAlertX processing cycle reported:

    Disconnections.........: 0
    

    Second occurrence

    At approximately 23:05, the same condition occurred again on the same Freebox TV Player Ethernet interface:

    host.active = True
    IPv4 active = True, reachable = False
    IPv6 link-local active = True, reachable = False
    all L3 entries reachable = False
    

    The fallback was triggered again:

    [FREEBOX] Host active but no reachable L3 address - using fallback IP
    

    The subsequent processing cycle again reported:

    Disconnections.........: 0
    

    Result

    This gives me two independent reproductions of the specific failure condition reported here.

    Previously, an active host with no reachable=true L3 entry could disappear from the FREEBOX plugin output and subsequently generate a false Disconnected state.

    With sha-067a6a1, the fallback keeps the host present in this condition, and neither of the two reproduced occurrences generated a disconnection.

    I did observe other Disconnected events during testing when the Freebox API itself reported the host as active=false, all L3 entries as inactive/unreachable, and no access point. I am treating those separately, since that is a different API state from the one reported in this issue.

    From my testing, the specific fix is working as intended.

  7. jokob-sk commented on Oct 2, 2026

    @jokob-sk
    Collaborator

    As always, thanks for testing and glad it's resolved -> will keep open until next release.

  8. removed
    Waiting for reply⏳Waiting for the original poster to respond, or discussion in progress.
    on Oct 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug 🐛Something isn't workingnext release/in dev image 🚀This is coming in the next release or was already released if the issue is Closed.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions