{"record":{"id":"20375a4eed675afe","repo":"AdguardTeam/AdGuardHome","slug":"adding-q-w","errorCode":null,"errorMessage":"adding %q: %w","messagePattern":"adding %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/aghos/fswatcher.go","lineNumber":149,"sourceCode":"\t// See https://pkg.go.dev/github.com/fsnotify/fsnotify@v1.7.0#readme-watching-a-file-doesn-t-work-well.\n\tdirName := name\n\tif !fi.IsDir() {\n\t\tdirName = filepath.Dir(name)\n\t}\n\n\tw.filesMu.Lock()\n\tdefer w.filesMu.Unlock()\n\n\tnames := w.files[dirName]\n\tif names == nil {\n\t\tnames = container.NewMapSet[string]()\n\t\tw.files[dirName] = names\n\t}\n\tnames.Add(name)\n\n\terr = w.watcher.Add(dirName)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"adding %q: %w\", dirName, err)\n\t}\n\n\treturn nil\n}\n\n// Remove implements the [FSWatcher] interface for *OSWatcher.  It's safe for\n// concurrent use.\nfunc (w *OSWatcher) Remove(name string) (err error) {\n\tdefer func() { err = errors.Annotate(err, \"%s: %w\", osWatcherPref) }()\n\n\tdirName := filepath.Dir(name)\n\n\tw.filesMu.Lock()\n\tdefer w.filesMu.Unlock()\n\n\tnames, ok := w.files[name]\n\tif ok {\n\t\tdirName = name","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/aghos/fswatcher.go#L131-L167","documentation":"dayRange.validate rejects a nonzero range whose end is negative: 'end <val> is negative'. A negative end cannot represent a valid time-of-day interval and fails schedule parsing immediately.","triggerScenarios":"A weekly schedule day with a negative end value (e.g. \"-02:00\" or negative duration) in JSON or YAML.","commonSituations":"Same as negative starts: timezone math, manual edits, or scripts emitting signed durations without clamping.","solutions":["Set end to a positive minute-aligned time within the day","Fix the generation logic to clamp or use absolute times","Disable the day by omitting it instead of using negatives","Add schedule validation to your config pipeline"],"exampleFix":"// before\n{\"start\": \"01:00\", \"end\": \"-02:00\"}\n// after\n{\"start\": \"01:00\", \"end\": \"02:00\"}","handlingStrategy":"validation","validationCode":"if end < 0 { end = 0 }","typeGuard":"func isNonNegative(d time.Duration) bool { return d >= 0 }","tryCatchPattern":"if err := unmarshalSchedule(data); err != nil && strings.Contains(err.Error(), \"is negative\") {\n    // fix end value, retry\n}","preventionTips":["Clamp computed durations to [0, 24h]","Omit disabled days entirely","Review timezone conversion code for sign errors"],"tags":["schedule","validation","time","config","go"],"backgroundTag":"config-validation-failed","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}