'nodeID' crashes DM handling after ban_hammer() writes a mismatched seenNodes entry #151

Closed
opened 2026-10-05 01:26:06 +02:00 by adam · 3 comments
Owner

Description

Once ban_hammer() in modules/system.py creates a new seenNodes entry, every subsequent DM to the bot fails with KeyError: 'nodeID', regardless of message content. The bot logs the DM as ignored and never processes it as a command.

Root Cause

ban_hammer() (modules/system.py, around line 1147) builds new seenNodes entries with the key node_id:

entry = {
    'node_id': node_id_str,
    'first_seen': current_time,
    'lastSeen': current_time,
    'auto_ban_count': 3,
    'rxInterface': rxInterface,
    'channel': channel,
    'welcome': False
}
seenNodes.append(entry)

Everywhere else that populates or reads seenNodes (mesh_bot.py, e.g. line 2124) uses the key nodeID instead. Once a node_id-keyed entry lands in the shared global list, this check in mesh_bot.py (line 2284) throws on it:

if not any(node['nodeID'] == message_from_id and node['welcome'] == True for node in seenNodes):

any() walks the entire seenNodes list, so the crash isn't limited to the node ban_hammer flagged. It breaks the welcome check for every node's DM from that point forward, until the service restarts and the in-memory list clears. seenNodes isn't persisted to disk, so a restart is a temporary workaround, not a fix.

The same unguarded node['nodeID'] pattern also appears at lines 701, 1832, and 2289, all vulnerable to the same issue. Line 2123 already uses node.get('nodeID') defensively, so the fix pattern already exists in the codebase, it's just not applied consistently.

Steps to Reproduce

  1. Trigger ban_hammer() for any node (repeated messages within the auto-ban timeframe/threshold).
  2. From a different node, send any DM to the bot.
  3. Bot logs Ignoring DM and the traceback below, and every DM from any node fails identically until restart.

Log Output

WARNING | Ignoring DM: <message> From: <node>
ERROR | System: Error processing packet: 'nodeID'
Traceback (most recent call last):
File "mesh_bot.py", line 2284, in onReceive
if not any(node['nodeID'] == message_from_id and node['welcome'] == True for node in seenNodes):
File "mesh_bot.py", line 2284, in <genexpr>
if not any(node['nodeID'] == message_from_id and node['welcome'] == True for node in seenNodes):
KeyError: 'nodeID'

Suggested Fix

Either:

  1. Change modules/system.py line ~1147 from 'node_id': node_id_str to 'nodeID': node_id_str, matching the schema used everywhere else, or
  2. Change the direct node['nodeID'] accesses in mesh_bot.py (lines 701, 1832, 2284, 2289) to node.get('nodeID'), so one malformed entry can't take down the whole check.

Option 1 fixes the root cause. Option 2 is defensive and worth doing regardless, since two schemas sharing one global list is a repeat risk.

Environment

  • meshing-around version/commit: 2.0.0
  • Install method: venv
## Description Once `ban_hammer()` in `modules/system.py` creates a new `seenNodes` entry, every subsequent DM to the bot fails with `KeyError: 'nodeID'`, regardless of message content. The bot logs the DM as ignored and never processes it as a command. ## Root Cause `ban_hammer()` (modules/system.py, around line 1147) builds new `seenNodes` entries with the key `node_id`: ```python entry = { 'node_id': node_id_str, 'first_seen': current_time, 'lastSeen': current_time, 'auto_ban_count': 3, 'rxInterface': rxInterface, 'channel': channel, 'welcome': False } seenNodes.append(entry) ``` Everywhere else that populates or reads `seenNodes` (mesh_bot.py, e.g. line 2124) uses the key `nodeID` instead. Once a `node_id`-keyed entry lands in the shared global list, this check in mesh_bot.py (line 2284) throws on it: ```python if not any(node['nodeID'] == message_from_id and node['welcome'] == True for node in seenNodes): ``` `any()` walks the entire `seenNodes` list, so the crash isn't limited to the node `ban_hammer` flagged. It breaks the welcome check for every node's DM from that point forward, until the service restarts and the in-memory list clears. `seenNodes` isn't persisted to disk, so a restart is a temporary workaround, not a fix. The same unguarded `node['nodeID']` pattern also appears at lines 701, 1832, and 2289, all vulnerable to the same issue. Line 2123 already uses `node.get('nodeID')` defensively, so the fix pattern already exists in the codebase, it's just not applied consistently. ## Steps to Reproduce 1. Trigger `ban_hammer()` for any node (repeated messages within the auto-ban timeframe/threshold). 2. From a different node, send any DM to the bot. 3. Bot logs `Ignoring DM` and the traceback below, and every DM from any node fails identically until restart. ## Log Output ``` WARNING | Ignoring DM: <message> From: <node> ERROR | System: Error processing packet: 'nodeID' Traceback (most recent call last): File "mesh_bot.py", line 2284, in onReceive if not any(node['nodeID'] == message_from_id and node['welcome'] == True for node in seenNodes): File "mesh_bot.py", line 2284, in <genexpr> if not any(node['nodeID'] == message_from_id and node['welcome'] == True for node in seenNodes): KeyError: 'nodeID' ``` ## Suggested Fix Either: 1. Change `modules/system.py` line ~1147 from `'node_id': node_id_str` to `'nodeID': node_id_str`, matching the schema used everywhere else, or 2. Change the direct `node['nodeID']` accesses in mesh_bot.py (lines 701, 1832, 2284, 2289) to `node.get('nodeID')`, so one malformed entry can't take down the whole check. Option 1 fixes the root cause. Option 2 is defensive and worth doing regardless, since two schemas sharing one global list is a repeat risk. ## Environment - meshing-around version/commit: 2.0.0 - Install method: venv <!-- github-sync-id:5538382513 -->
adam closed this issue 2026-10-05 01:26:06 +02:00
Author
Owner

this may resolve the issue?

this may resolve the issue? <!-- github-comment-id:5781162803 -->
Author
Owner

Ok I just did the update. So far promising.

Ok I just did the update. So far promising. <!-- github-comment-id:5786651401 -->
Author
Owner

Thanks for catching it, typo on my end.

Thanks for catching it, typo on my end. <!-- github-comment-id:5786720458 -->
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: adam/meshing-around#151