From 3e124dd4b38450ebcaaf92558a87f601d7739bb8 Mon Sep 17 00:00:00 2001 From: archipelago Date: Thu, 6 Aug 2026 09:28:44 -0400 Subject: [PATCH] fix(rpc): surface unknown-method + RNode settings errors instead of masking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deploying the .126 LoRa panel ahead of its daemon made every button report "Operation failed. Check server logs for details." — the panel was calling RPCs the older binary doesn't have, and the sanitizer masked "Unknown method: mesh.rnode-config" into that generic string. Read as "the feature is broken" rather than "this node needs its update" (operator, 2026-08-06). Allowlisted: "Unknown method" (a frontend newer than its daemon should say so), every RNode RF validation message (each names the field and its legal range — the entire point of validating before touching the radio), and the actionable mesh preconditions (no device connected, mesh service not running, MeshCore has no remote reboot, radio daemon did not answer, RNode interface disabled). Co-Authored-By: Claude Fable 5 --- core/archipelago/src/api/rpc/middleware.rs | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/core/archipelago/src/api/rpc/middleware.rs b/core/archipelago/src/api/rpc/middleware.rs index bba77598..0b6c093e 100644 --- a/core/archipelago/src/api/rpc/middleware.rs +++ b/core/archipelago/src/api/rpc/middleware.rs @@ -84,6 +84,33 @@ pub(super) fn sanitize_error_message(msg: &str) -> String { // Masking sent the operator to journalctl again (framework-pt // sweep, 2026-08-06) — same lesson as the two above. "Failed to send", + // A frontend newer than the daemon calls methods it doesn't have. + // Masked, this reads as "the feature is broken" instead of "this + // node needs its update" — hit live the moment the .126 LoRa panel + // was deployed ahead of its binary (2026-08-06). + "Unknown method", + // RNode RF settings validation (mesh::rnode_settings::validate) — + // every one names the offending field and its legal range, which is + // the entire point of validating before touching the radio. + "frequency ", + "bandwidth ", + "spreading factor ", + "coding rate ", + "tx power ", + "airtime_limit_short", + "airtime_limit_long", + "port must be an absolute", + "Invalid settings", + "Missing 'settings'", + // Mesh preconditions the operator can act on directly. + "Mesh service not running", + "No mesh device connected", + "Mesh listener not running", + "MeshCore radios have no remote reboot", + "Radio state read-back", + "The radio daemon did not answer", + "The radio did not acknowledge", + "RNode interface is disabled", // Lightning payment failures carry LND's reason ("invoice expired. // Valid until …", "no route", …) — the user can act on every one of // them, and masking sent the operator to journalctl (invoice-expired