From a1573c6018c2e81795dc87d36011604dfed80936 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Tue, 27 Jan 2026 13:56:45 +0000 Subject: fix: prevent git protocol errors from triggering naughty list Change protocol error detection to only match WebSocket-specific errors (websocket, invalid frame) instead of generic 'protocol' keyword which was incorrectly catching transient git protocol errors. Git protocol errors like 'fatal: protocol error: bad line length' are transient network issues that should use backoff/retry, not permanent naughty list blocking. Only WebSocket/Nostr protocol violations indicate persistent infrastructure problems. Fixes production false positive: - relay.ngit.dev: git protocol error + remote warning misclassified Add production test cases for git protocol errors and warning combinations. --- src/sync/naughty_list.rs | 77 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/sync/naughty_list.rs b/src/sync/naughty_list.rs index 60ab949..0abb986 100644 --- a/src/sync/naughty_list.rs +++ b/src/sync/naughty_list.rs @@ -232,12 +232,12 @@ impl NaughtyListTracker { } } - // Protocol errors - if error_lower.contains("websocket") - || error_lower.contains("protocol") - || error_lower.contains("invalid frame") - { - // Exclude connection errors + // Protocol errors - specifically WebSocket/Nostr protocol violations + // Note: We check for "websocket" specifically, NOT generic "protocol" keyword + // because git errors often contain "protocol error" (e.g., "fatal: protocol error: bad line length") + // which are transient network issues, not persistent infrastructure problems. + if error_lower.contains("websocket") || error_lower.contains("invalid frame") { + // Exclude connection errors (transient) if !error_lower.contains("connection") && !error_lower.contains("timeout") && !error_lower.contains("refused") @@ -622,3 +622,68 @@ mod tests { assert_eq!(NaughtyCategory::ProtocolError.as_str(), "protocol_error"); } } + +#[cfg(test)] +mod production_tests { + use super::*; + + /// Production case from relay.ngit.dev - remote warning should not be classified + #[test] + fn test_classify_production_relay_ngit_dev_warning() { + let error = + "remote: warning: unable to access '/root/.config/git/attributes': Permission denied"; + assert_eq!(NaughtyListTracker::classify_error(error), None); + } + + /// Git protocol errors are transient, not persistent infrastructure issues + #[test] + fn test_git_protocol_errors_not_naughty() { + // These are common git protocol errors that should NOT be classified as naughty + let git_protocol_errors = [ + "fatal: protocol error: bad line length character: remo", + "fatal: protocol error: expected old/new/ref, got 'shallow", + "fatal: git upload-pack: protocol error", + "error: protocol error: bad pack header", + "fatal: protocol error: bad band #3", + ]; + + for error in git_protocol_errors { + assert_eq!( + NaughtyListTracker::classify_error(error), + None, + "Git protocol error should not be classified as naughty: {}", + error + ); + } + } + + /// Remote warning followed by git protocol error - both should be filtered/ignored + #[test] + fn test_warning_with_git_protocol_error() { + let error = "remote: warning: unable to access '/root/.config/git/attributes': Permission denied\nfatal: protocol error: bad line length character: remo"; + assert_eq!( + NaughtyListTracker::classify_error(error), + None, + "Warning + git protocol error should not be classified as naughty" + ); + } + + /// WebSocket protocol errors ARE naughty (persistent infrastructure issues) + #[test] + fn test_websocket_errors_still_naughty() { + let websocket_errors = [ + "websocket protocol error", + "websocket handshake failed", + "invalid frame received", + ]; + + for error in websocket_errors { + assert_eq!( + NaughtyListTracker::classify_error(error), + Some(NaughtyCategory::ProtocolError), + "WebSocket error should be classified as protocol_error: {}", + error + ); + } + } +} -- cgit v1.2.3