dapr/dapr · error
error parsing %s due time: %w
Error message
error parsing %s due time: %w
What it means
setReminderTimes parses dueTime with timeutils.ParseTime. That helper accepts either an RFC3339 timestamp ("2025-01-02T15:04:05Z") or a Go duration relative to now ("90s", "1h"). logMsg tells you whether the failing object is a reminder or a timer. An invalid dueTime string produces this error.
Source
Thrown at pkg/actors/api/reminders.go:188
if len(m.Data) > 0 {
req.Data, err = anypb.New(wrapperspb.Bytes(m.Data))
if err != nil {
return fmt.Errorf("failed to unmarshal data: %w", err)
}
}
return nil
}
func setReminderTimes(reminder *Reminder, dueTime string, period string, ttl string, now time.Time, logMsg string) (err error) {
// Due time and registered time
reminder.RegisteredTime = now
reminder.DueTime = dueTime
if dueTime != "" {
reminder.RegisteredTime, err = parseReminderTime(dueTime, &now)
if err != nil {
return fmt.Errorf("error parsing %s due time: %w", logMsg, err)
}
}
// Parse period and check correctness
reminder.Period, err = NewReminderPeriod(period)
if err != nil {
return fmt.Errorf("invalid %s period: %w", logMsg, err)
}
// Set expiration time if configured
if ttl != "" {
reminder.ExpirationTime, err = parseReminderTime(ttl, &reminder.RegisteredTime)
if err != nil {
return fmt.Errorf("error parsing %s TTL: %w", logMsg, err)
}
// check if already expired
if now.After(reminder.ExpirationTime) || reminder.RegisteredTime.After(reminder.ExpirationTime) {
return fmt.Errorf("%s %s has already expired: dueTime: %s TTL: %s",View on GitHub (pinned to 74ad417027)
Solutions
- Use an RFC3339 string with timezone ("2025-01-02T15:04:05Z") or a Go duration ("5m").
- Omit dueTime (empty string) to fire at registration time.
- Validate on the client with the same rule: try time.Parse(time.RFC3339, v), then time.ParseDuration(v).
Example fix
// before
{"dueTime":"2025-01-02 15:04:05","period":"30s"}
// after
{"dueTime":"2025-01-02T15:04:05Z","period":"30s"} Defensive patterns
Strategy: validation
Validate before calling
import timeutils "github.com/dapr/kit/time"
func validReminderTime(v string) bool {
if v == "" {
return true
}
now := time.Now()
_, err := timeutils.ParseTime(v, &now)
return err == nil
} Try / catch
if err := client.RegisterReminder(ctx, req); err != nil {
if strings.Contains(err.Error(), "due time") {
// bad dueTime string: fix input; parse failures are permanent
}
} Prevention
- Format absolute times with t.Format(time.RFC3339).
- Test relative values with time.ParseDuration before sending.
- Never retry a request with the same invalid string.
When it happens
Trigger: CreateReminder/CreateTimer, or the HTTP APIs POST /actors/{type}/{id}/reminders and /timers, sends dueTime that is neither RFC3339 nor a Go duration: "tomorrow", "1hour", "2025-01-02 15:04:05" (missing T and zone), or an empty placeholder like "null".
Common situations: A date is formatted without the T separator or timezone offset. A relative value spells out a unit Go rejects. A UI passes free-text input straight into the request.
Related errors
- error parsing %s TTL: %w
- parse error: %w
- invalid %s period: %w
- %s %s has already expired: dueTime: %s TTL: %s
- failed to unmarshal data: %w
AI-assisted analysis of dapr/dapr@74ad417027 (2026-08-16).
Data as JSON: /api/errors/cbdf4a2b43821fef.
Report an issue: GitHub.