Error Message Improvement Report — tailstick
Repository: Microck/tailstick
Files analyzed: 16 Go source files (12 non-test, 4 test)
Date: 2026-04-18
Severity Definitions
| Level |
Meaning |
| P0 |
Error swallows underlying cause entirely (no %w wrapping) — impossible to diagnose programmatically |
| P1 |
Error message is vague, lacks context, or is misleading — user/admin cannot act on it |
| P2 |
Error is adequately wrapped but message could be more specific/actionable |
| P3 |
Minor wording improvement; nice-to-have |
P0 — Errors That Swallow Underlying Causes (17 locations)
1. crypto/secret.go — Entire Encrypt and Decrypt functions pass through bare errors
Lines: 31, 34, 37, 43, 54, 60, 64, 68, 72, 76, 81, 84, 87, 92, 101, 110, 125
Every error in Encrypt() and Decrypt() is returned as raw err with no wrapping. When encryption/decryption fails, the caller gets a bare cipher: message authentication failed with zero indication it came from the crypto package.
Fix: Wrap all errors with fmt.Errorf("operation description: %w", err).
2. state/store.go — Save() returns bare errors (lines 42, 46, 50, 52)
os.MkdirAll, json.MarshalIndent, os.WriteFile, os.Rename all return bare errors.
3. state/store.go — AppendAudit() returns bare errors (lines 68, 73, 78, 81)
Same pattern — all audit file operations return bare errors.
4. logging/logger.go — New() returns bare errors (lines 23, 27)
5. platform/platform.go — EnsureParent() returns bare error (line 91)
6. app/workflow.go — Multiple bare error returns in Enroll() (lines 98, 102, 148, 153, 157, 186, 190, 207)
7. app/workflow.go — AgentOnce(), AgentRun(), ForceCleanup() (lines 217, 242, 268, 289, 302)
8. tailscale/client.go — deleteDevice() returns bare errors for HTTP (lines 153, 158)
P1 — Vague or Missing Context (13 locations)
Key examples:
crypto/secret.go line 120 — "empty key material" → should explain both password and machineContext are empty
tailscale/client.go line 64 — "missing auth key" → should explain where to set it
tailscale/client.go line 59 — "session mode requires ephemeral auth key" → should say which config field
tailscale/client.go line 45 — "stable channel requires configured stable version" → should say where to pin version
app/workflow.go line 106 — "operator password is invalid" → should explain CLI flags/env vars
app/workflow.go line 635 — "preset %s does not allow exit node selection" → should say allowExitNodeSelection=true
platform/platform.go lines 146, 152 — Linux distro messages give no guidance
P2 — Wrapped but Could Be More Specific (8 locations)
config/config.go lines 28, 35 — missing file path in error
tailscale/client.go line 169 — missing device ID for correlation
gui/server.go line 71 — port validation could suggest using 0
gui/server.go line 139 — "invalid json body" doesn't include parse error
P3 — Minor Wording (7 locations)
Various config validation and CLI error messages could be more specific.
Summary
| Severity |
Count |
Description |
| P0 |
17 locations |
Bare errors with no wrapping |
| P1 |
13 locations |
Vague or missing context |
| P2 |
8 locations |
Could be more specific |
| P3 |
7 locations |
Minor wording |
| Total |
45 findings |
Across 8 source files |
Key Patterns
crypto/secret.go has 15 bare error returns — worst offender, fix first
state/store.go has 6 bare errors — state persistence loses diagnostic context
app/workflow.go has ~20 bare errors scattered through enrollment, agent, and cleanup flows
- No errors use
errors.Is()/errors.As() sentinel patterns
Generated by Nightshift v3 (GLM 5.1)
Error Message Improvement Report — tailstick
Repository: Microck/tailstick
Files analyzed: 16 Go source files (12 non-test, 4 test)
Date: 2026-04-18
Severity Definitions
%wwrapping) — impossible to diagnose programmaticallyP0 — Errors That Swallow Underlying Causes (17 locations)
1.
crypto/secret.go— EntireEncryptandDecryptfunctions pass through bare errorsLines: 31, 34, 37, 43, 54, 60, 64, 68, 72, 76, 81, 84, 87, 92, 101, 110, 125
Every error in
Encrypt()andDecrypt()is returned as rawerrwith no wrapping. When encryption/decryption fails, the caller gets a barecipher: message authentication failedwith zero indication it came from the crypto package.Fix: Wrap all errors with
fmt.Errorf("operation description: %w", err).2.
state/store.go—Save()returns bare errors (lines 42, 46, 50, 52)os.MkdirAll,json.MarshalIndent,os.WriteFile,os.Renameall return bare errors.3.
state/store.go—AppendAudit()returns bare errors (lines 68, 73, 78, 81)Same pattern — all audit file operations return bare errors.
4.
logging/logger.go—New()returns bare errors (lines 23, 27)5.
platform/platform.go—EnsureParent()returns bare error (line 91)6.
app/workflow.go— Multiple bare error returns inEnroll()(lines 98, 102, 148, 153, 157, 186, 190, 207)7.
app/workflow.go—AgentOnce(),AgentRun(),ForceCleanup()(lines 217, 242, 268, 289, 302)8.
tailscale/client.go—deleteDevice()returns bare errors for HTTP (lines 153, 158)P1 — Vague or Missing Context (13 locations)
Key examples:
crypto/secret.goline 120 —"empty key material"→ should explain both password and machineContext are emptytailscale/client.goline 64 —"missing auth key"→ should explain where to set ittailscale/client.goline 59 —"session mode requires ephemeral auth key"→ should say which config fieldtailscale/client.goline 45 —"stable channel requires configured stable version"→ should say where to pin versionapp/workflow.goline 106 —"operator password is invalid"→ should explain CLI flags/env varsapp/workflow.goline 635 —"preset %s does not allow exit node selection"→ should sayallowExitNodeSelection=trueplatform/platform.golines 146, 152 — Linux distro messages give no guidanceP2 — Wrapped but Could Be More Specific (8 locations)
config/config.golines 28, 35 — missing file path in errortailscale/client.goline 169 — missing device ID for correlationgui/server.goline 71 — port validation could suggest using 0gui/server.goline 139 —"invalid json body"doesn't include parse errorP3 — Minor Wording (7 locations)
Various config validation and CLI error messages could be more specific.
Summary
Key Patterns
crypto/secret.gohas 15 bare error returns — worst offender, fix firststate/store.gohas 6 bare errors — state persistence loses diagnostic contextapp/workflow.gohas ~20 bare errors scattered through enrollment, agent, and cleanup flowserrors.Is()/errors.As()sentinel patternsGenerated by Nightshift v3 (GLM 5.1)