1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! What a network peer may be told when netget itself fails.
//!
//! **Rule: an internal error string never reaches the wire.** Not the LLM backend's error,
//! not an `anyhow` context chain, not a serde or codec message. Those name the model, the
//! backend URL, the request body, file paths and library internals; the peer is a stranger
//! and none of it is theirs to read. It goes to the log and the TUI status stream, which is
//! where an operator looks.
//!
//! This is not a hypothetical. Every protocol that answers its peer on backend failure used
//! to interpolate the error into the reply, so a plain `telnet` session got
//! `[netget] cannot answer right now: ✗ LLM failed to generate valid response after retries.`
//! — netget's own retry machinery, verbatim, on a stranger's terminal.
//!
//! A peer still needs an answer: silence leaves it blocked until its own timeout, which is
//! the failure mode CLAUDE.md calls out as worse than refusing. So the protocols keep
//! answering — they just answer with a *category*, not a diagnosis.
//!
//! ## Why `&'static str`
//!
//! [`WireFailure::text`] returns `&'static str` on purpose. A function that took an error and
//! returned `String` would be one `format!` away from leaking again, and that is exactly how
//! the original bug spread: each protocol copied its neighbour. A `&'static str` cannot carry
//! anything derived from the error, so the guarantee is in the type rather than in reviewer
//! attention.
//!
//! The error is still passed in — but only to *classify* it, never to render it.
/// How an internal failure is described to a network peer.
/// Shorthand for [`WireFailure::classify`] + [`WireFailure::text`].
/// Shorthand for [`WireFailure::classify`] + [`WireFailure::prefixed_text`].