@@ -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+
230263func truncate (s string , maxLen int ) string {
231264 if len (s ) <= maxLen {
232265 return s
0 commit comments