{"record":{"id":"7f3c7c3505a1bd96","repo":"chenhg5/cc-connect","slug":"invalid-delay-or-time-q-use-duration-like-2h30m","errorCode":null,"errorMessage":"invalid delay or time %q (use duration like 2h30m, or ISO time like 2026-05-15T14:00)","messagePattern":"invalid delay or time %q \\(use duration like 2h30m, or ISO time like 2026-05-15T14:00\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/timer.go","lineNumber":488,"sourceCode":"\t\t{time.RFC3339, false},\n\t\t{\"2006-01-02T15:04:05\", true},\n\t\t{\"2006-01-02T15:04\", true},\n\t\t{\"2006-01-02 15:04:05\", true},\n\t\t{\"2006-01-02 15:04\", true},\n\t}\n\tfor _, l := range layouts {\n\t\tif l.local {\n\t\t\tif t, err := time.ParseInLocation(l.layout, s, time.Local); err == nil {\n\t\t\t\treturn t, nil\n\t\t\t}\n\t\t} else {\n\t\t\tif t, err := time.Parse(l.layout, s); err == nil {\n\t\t\t\treturn t, nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn time.Time{}, fmt.Errorf(\"invalid delay or time %q (use duration like 2h30m, or ISO time like 2026-05-15T14:00)\", s)\n}\n\n// FormatTimerRemaining returns a human-readable string for time remaining\n// until the scheduled fire time.\nfunc FormatTimerRemaining(scheduledAt time.Time) string {\n\td := time.Until(scheduledAt)\n\tif d <= 0 {\n\t\treturn \"overdue\"\n\t}\n\tif d < time.Minute {\n\t\tsecs := int(d.Seconds() + 0.5) // round up for countdown display\n\t\tif secs >= 60 {\n\t\t\treturn \"1m\"\n\t\t}\n\t\treturn fmt.Sprintf(\"%ds\", secs)\n\t}\n\tif d < time.Hour {\n\t\tmins := int(d.Minutes() + 0.5) // round up for countdown display","sourceCodeStart":470,"sourceCodeEnd":506,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/timer.go#L470-L506","documentation":"This is the final fallback error of ParseDelayOrTime: the input is non-empty, failed time.ParseDuration, and matched none of the supported ISO/local time layouts. The message quotes the offending input and states both accepted formats so the user can self-correct.","triggerScenarios":"Calling ParseDelayOrTime with a string that is neither a Go duration nor one of the supported time layouts, e.g. \"tomorrow 5pm\", \"15/05/2026 14:00\", \"next monday\", or an ISO date without time \"2026-05-15\".","commonSituations":"Users writing natural-language times ('in two hours', 'tonight'); locale-formatted dates (dd/mm/yyyy); missing seconds/timezone assumptions; passing a date-only string when a time is required.","solutions":["Use a Go duration string: '2h', '30m', '1h30m', '2h30m15s'.","Use an ISO 8601 time like '2026-05-15T14:00' or with timezone '2026-05-15T14:00:00+08:00'.","Translate natural-language or locale dates to one of the supported formats before calling (e.g. with a dateparse library or LLM preprocessing in the command handler).","Check the error text: it echoes the rejected input in %q, confirming what was actually parsed."],"exampleFix":"// before\nat, err := core.ParseDelayOrTime(\"tomorrow 5pm\")\n// after\nat, err := core.ParseDelayOrTime(\"24h\") // or \"2026-05-16T17:00\"","handlingStrategy":"validation","validationCode":"func looksLikeDelayOrTime(s string) bool {\n    if _, err := time.ParseDuration(s); err == nil { return true }\n    for _, layout := range []string{time.RFC3339, \"2006-01-02T15:04\", \"2006-01-02T15:04:05\"} {\n        if _, err := time.Parse(layout, s); err == nil { return true }\n    }\n    return false\n}","typeGuard":null,"tryCatchPattern":"at, err := core.ParseDelayOrTime(arg)\nif err != nil {\n    reply(fmt.Sprintf(\"Could not understand %q. Use 2h30m or 2026-05-15T14:00.\", arg))\n    return\n}","preventionTips":["Document accepted formats in the command's help/usage output.","Reject natural-language dates upstream or convert them before parsing.","Echo the offending input back to the user on failure.","Add unit tests covering locale date strings users commonly type."],"tags":["timer","parsing","duration","date-format"],"backgroundTag":"invalid-date-format","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}