chenhg5/cc-connect · error

empty delay or time

Error message

empty delay or time

What it means

ParseDelayOrTime in core/timer.go parses a relative Go duration or an absolute ISO time for a timer. It first trims the input; if the result is an empty string there is nothing to parse, so it immediately returns this error instead of attempting any format detection. It is a guard against callers passing blank scheduling input.

Source

Thrown at core/timer.go:451

		slog.Info("timer: job completed", "id", jobID)
	}
}

func GenerateTimerID() string {
	b := make([]byte, 4)
	if _, err := rand.Read(b); err != nil {
		panic(fmt.Errorf("generate timer id: %w", err))
	}
	return hex.EncodeToString(b)
}

// ParseDelayOrTime parses a relative duration ("2h", "30m", "1h30m") or
// an absolute ISO time ("2026-05-15T14:00", "2026-05-15T14:00:00+08:00")
// and returns the absolute fire time.
func ParseDelayOrTime(s string) (time.Time, error) {
	s = strings.TrimSpace(s)
	if s == "" {
		return time.Time{}, fmt.Errorf("empty delay or time")
	}

	// Try as a Go duration first (e.g., "2h", "30m", "1h30m", "2h30m15s")
	if d, err := time.ParseDuration(s); err == nil {
		if d <= 0 {
			return time.Time{}, fmt.Errorf("delay must be positive")
		}
		return time.Now().Add(d), nil
	}

	// Try ISO time formats
	// RFC3339 includes timezone (e.g. "2026-05-15T14:00:00+08:00"),
	// so it's parsed directly. The other layouts have no timezone
	// and are interpreted in the system's local timezone.
	layouts := []struct {
		layout string
		local  bool
	}{

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Provide a non-empty value: a positive duration like '2h30m' or an ISO time like '2026-05-15T14:00'.
  2. In command handlers, check the argument for emptiness before calling ParseDelayOrTime and reply with usage text.
  3. If the value comes from user input, trim whitespace and reject blank input upstream with a friendlier message.

Example fix

// before
tm, err := core.ParseDelayOrTime(arg)
// after
if strings.TrimSpace(arg) == "" {
    return fmt.Errorf("usage: /timer add <2h30m | 2026-05-15T14:00>")
}
tm, err := core.ParseDelayOrTime(arg)
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(arg) == "" {
    return fmt.Errorf("timer: delay or time is required (e.g. 2h30m or 2026-05-15T14:00)")
}
_, err := core.ParseDelayOrTime(arg)

Try / catch

if _, err := core.ParseDelayOrTime(arg); err != nil {
    if err.Error() == "empty delay or time" {
        reply("Usage: /timer add <duration|ISO-time>")
        return
    }
    reply("Invalid timer: " + err.Error())
}

Prevention

When it happens

Trigger: Calling ParseDelayOrTime("") or ParseDelayOrTime(" ") — any string that is empty or whitespace-only after strings.TrimSpace. Reachable via timer add commands (handleTimerAdd, cmdTimerAdd, cmdTimerAddExec) when the user supplies no delay/time argument.

Common situations: User runs the timer add command with a missing argument (e.g. '/timer add' with no value); a bot integration forwards an unset or stripped field; a shell expansion or variable interpolation produced an empty string.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/0fe29e4cb9354315. Report an issue: GitHub.