Skip to content

Commit 4b60543

Browse files
committed
Show skipped files with reasons in Slack warning notifications
When backup completes with exit code 3 (partial), the Slack notification now lists each skipped file with its error reason (up to 20, with count).
1 parent 05f840d commit 4b60543

File tree

1 file changed

+34
-1
lines changed

1 file changed

+34
-1
lines changed

internal/backup/backup.go

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,10 @@ func (o *Orchestrator) Run(ctx context.Context) error {
110110

111111
// Notify
112112
if backupResult.ExitCode == restic.ExitPartial {
113+
skipped := extractErrors(backupResult.Stderr, 20)
114+
extra := fmt.Sprintf("*%d files skipped:*\n```\n%s\n```", countErrors(backupResult.Stderr), skipped)
113115
o.notifyWarning("Backup Completed with Warnings",
114-
formatSummary(backupResult, duration, "Some files were skipped (locked or permission denied). Check logs for details."))
116+
formatSummary(backupResult, duration, extra))
115117
} else {
116118
o.notifySuccess("Backup Successful",
117119
formatSummary(backupResult, duration, ""))
@@ -227,6 +229,37 @@ func formatSummary(result *restic.Result, duration time.Duration, extra string)
227229
return sb.String()
228230
}
229231

232+
// extractErrors pulls error/warning lines from restic stderr output.
233+
// Each line includes the file path and reason (e.g. "Access is denied", "locked").
234+
// Returns up to maxLines lines to keep Slack messages reasonable.
235+
func extractErrors(stderr string, maxLines int) string {
236+
var errors []string
237+
for _, line := range strings.Split(stderr, "\n") {
238+
line = strings.TrimSpace(line)
239+
if strings.HasPrefix(line, "error:") || strings.HasPrefix(line, "warning:") {
240+
errors = append(errors, line)
241+
}
242+
}
243+
total := len(errors)
244+
if total > maxLines {
245+
errors = errors[:maxLines]
246+
errors = append(errors, fmt.Sprintf("... and %d more", total-maxLines))
247+
}
248+
return strings.Join(errors, "\n")
249+
}
250+
251+
// countErrors returns the total number of error/warning lines in restic stderr.
252+
func countErrors(stderr string) int {
253+
count := 0
254+
for _, line := range strings.Split(stderr, "\n") {
255+
line = strings.TrimSpace(line)
256+
if strings.HasPrefix(line, "error:") || strings.HasPrefix(line, "warning:") {
257+
count++
258+
}
259+
}
260+
return count
261+
}
262+
230263
func truncate(s string, maxLen int) string {
231264
if len(s) <= maxLen {
232265
return s

0 commit comments

Comments
 (0)