larksuite/cli · error
cannot parse %q as ISO 8601
Error message
cannot parse %q as ISO 8601
What it means
This is the sentinel error returned by parseISO8601 when the input string matches none of its four supported layouts: time.RFC3339 (2006-01-02T15:04:05Z07:00), 2006-01-02T15:04Z07:00, 2006-01-02T15:04:05, and 2006-01-02T15:04. It includes the offending string in %q but is usually wrapped (and its detail dropped) by callers like the set_calendar validation, which replace it with a generic 'must be a valid ISO 8601 timestamp' message.
Source
Thrown at shortcuts/mail/draft/model.go:453
panic(fmt.Sprintf("MustJSON: %v", err))
}
return string(data)
}
// parseISO8601 tries common ISO 8601 timestamp layouts, accepting both
// with-seconds (RFC 3339) and without-seconds variants.
func parseISO8601(s string) (time.Time, error) {
for _, layout := range []string{
time.RFC3339,
"2006-01-02T15:04Z07:00",
"2006-01-02T15:04:05",
"2006-01-02T15:04",
} {
if t, err := time.Parse(layout, s); err == nil {
return t, nil
}
}
return time.Time{}, fmt.Errorf("cannot parse %q as ISO 8601", s)
}
View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Normalize to RFC 3339 with seconds and offset before submitting: t.Format(time.RFC3339)
- If your timestamps have fractional seconds, strip them or format with a matching layout (e.g. 2026-09-04T10:00:00Z without milliseconds)
- Replace the space separator with 'T' and ensure offsets use the +08:00 colon form (or Z for UTC)
- Accept one of the four exact shapes: with/without seconds, with/without timezone — no date-only or epoch forms
Example fix
// before ts := "2026-09-04 10:00:00+0800" // rejected // after ts := "2026-09-04T10:00:00+08:00" // accepted (RFC 3339)
Defensive patterns
Strategy: validation
Validate before calling
func normalizeISO8601(s string) (string, error) {
t, err := time.Parse(time.RFC3339, s)
if err != nil {
return "", fmt.Errorf("timestamp %q must be RFC 3339 (e.g. 2026-09-04T10:00:00Z)", s)
}
return t.Format(time.RFC3339), nil
} Prevention
- Normalize timestamps to RFC 3339 at the boundary of your program, once
- Avoid fractional seconds, '+0800' colon-less offsets, and space separators — none match the parser's layouts
- Store and transmit timestamps as RFC 3339 strings or time.Time, never as display-formatted strings
- Add a test that round-trips every timestamp your system emits through time.Parse(time.RFC3339, ...)
When it happens
Trigger: Any call path that funnels a timestamp through parseISO8601 (currently set_calendar event_start/event_end) with input such as date-only strings, epoch numbers as strings, 'YYYY-MM-DD HH:MM:SS' (space instead of T), offsets without colons ('+0800'), or trailing garbage after a valid timestamp.
Common situations: RFC 3339 fractional seconds like 2026-09-04T10:00:00.123Z (the parser layouts do not include fractional seconds); '+0800' offsets missing the colon; lowercase 'z' or 't' separators; copying timestamps from databases (e.g. Postgres '2026-09-04 10:00:00+08').
Related errors
- must be a nonnegative integer: %w
- set_calendar: event_start must be a valid ISO 8601 timestamp
- set_calendar: event_end must be a valid ISO 8601 timestamp
- date %q must be ISO yyyy-mm-dd: %w
- datetime %q must be ISO: %w
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/8a42042965942bd8.
Report an issue: GitHub.