Skip to content

Commit e44a8e2

Browse files
wesmclaude
andauthored
Truncate long MIME parse error messages (#202)
## Summary - Cap `FirstLine()` output at 200 runes using the existing `TruncateRunes` helper - Prevents enmime's malformed-MIME error messages (which embed the full email content as a single line) from flooding console output during sync - Uses rune-safe truncation to avoid splitting multi-byte UTF-8 characters in non-ASCII error text ## Test plan - [x] Existing `TestFirstLine` tests pass - [x] New test cases: long ASCII lines, exact boundary (200 runes), long first line of multi-line, and Unicode truncation safety 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 98f3186 commit e44a8e2

File tree

2 files changed

+10
-5
lines changed

2 files changed

+10
-5
lines changed

internal/textutil/encoding.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,14 @@ func TruncateRunes(s string, maxRunes int) string {
136136
return string(runes[:maxRunes-3]) + "..."
137137
}
138138

139-
// FirstLine returns the first line of a string.
140-
// Useful for extracting clean error messages from multi-line outputs.
141-
// Leading newlines are trimmed before extracting the first line.
139+
// FirstLine returns the first line of a string, capped at 200 runes.
140+
// Useful for extracting clean error messages from multi-line outputs
141+
// where the first line itself may be excessively long (e.g. enmime
142+
// includes malformed MIME content in its error messages).
142143
func FirstLine(s string) string {
143144
s = strings.TrimLeft(s, "\r\n")
144145
if idx := strings.Index(s, "\n"); idx >= 0 {
145-
return s[:idx]
146+
s = s[:idx]
146147
}
147-
return s
148+
return TruncateRunes(s, 200)
148149
}

internal/textutil/encoding_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,10 @@ func TestFirstLine(t *testing.T) {
486486
{"leading carriage return", "\r\nSecond", "Second"},
487487
{"mixed leading newlines", "\r\n\n\rThird", "Third"},
488488
{"only newlines", "\n\n\n", ""},
489+
{"long line truncated", strings.Repeat("x", 250), strings.Repeat("x", 197) + "..."},
490+
{"exactly 200 runes", strings.Repeat("y", 200), strings.Repeat("y", 200)},
491+
{"long first line of multi", strings.Repeat("z", 250) + "\nSecond", strings.Repeat("z", 197) + "..."},
492+
{"unicode truncation safe", strings.Repeat("é", 250), strings.Repeat("é", 197) + "..."},
489493
}
490494
for _, tt := range tests {
491495
t.Run(tt.name, func(t *testing.T) {

0 commit comments

Comments
 (0)