gastownhall/beads · error
empty timestamp
Error message
empty timestamp
What it means
ParseTimestamp rejects an empty string input before attempting any format parsing. Jira timestamps are ISO 8601 strings; an empty value means the upstream JSON field was absent, null, or an empty string, and no meaningful time can be produced. The zero time.Time and this error are returned to all callers (FetchIssueTimestamp, jiraToTrackerIssue, anonymous closures).
Source
Thrown at internal/jira/refs.go:42
return true
}
// ExtractJiraKey extracts the Jira issue key from an external_ref URL.
// For example, "https://company.atlassian.net/browse/PROJ-123" returns "PROJ-123".
func ExtractJiraKey(externalRef string) string {
idx := strings.LastIndex(externalRef, "/browse/")
if idx == -1 {
return ""
}
return externalRef[idx+len("/browse/"):]
}
// ParseTimestamp parses Jira's timestamp format into a time.Time.
// Jira uses ISO 8601 with timezone: 2024-01-15T10:30:00.000+0000 or 2024-01-15T10:30:00.000Z
func ParseTimestamp(ts string) (time.Time, error) {
if ts == "" {
return time.Time{}, fmt.Errorf("empty timestamp")
}
// Try common formats
formats := []string{
"2006-01-02T15:04:05.000-0700",
"2006-01-02T15:04:05.000Z",
"2006-01-02T15:04:05-0700",
"2006-01-02T15:04:05Z",
time.RFC3339,
time.RFC3339Nano,
}
for _, format := range formats {
if t, err := time.Parse(format, ts); err == nil {
return t, nil
}
}
View on GitHub (pinned to 71377f2769)
Solutions
- Check the field is non-empty before calling ParseTimestamp and handle the unset case explicitly.
- Default to a sentinel (e.g. time.Time{} or the issue's created timestamp) when the field is legitimately empty.
- Inspect the raw Jira JSON response to confirm which field is empty and whether that is expected.
- If the field should never be empty, check for Jira instance/plugin issues or API version differences.
Example fix
// before
updated, err := jira.ParseTimestamp(issue.Fields.Updated)
// after
var updated time.Time
if issue.Fields.Updated != "" {
updated, err = jira.ParseTimestamp(issue.Fields.Updated)
if err != nil { return err }
} else {
updated, _ = jira.ParseTimestamp(issue.Fields.Created)
} Defensive patterns
Strategy: validation
Validate before calling
func safeParseTimestamp(ts string) (time.Time, error) {
if strings.TrimSpace(ts) == "" {
return time.Time{}, nil // treat unset as zero-value, not an error
}
return jira.ParseTimestamp(ts)
} Type guard
func hasTimestamp(s string) bool {
return strings.TrimSpace(s) != ""
} Try / catch
t, err := jira.ParseTimestamp(ts)
if err != nil {
if strings.Contains(err.Error(), "empty timestamp") {
t = time.Time{} // or fall back to Created
} else {
return err
}
} Prevention
- Always null/empty-check Jira timestamp fields before parsing.
- Prefer omitempty-aware struct unmarshaling so missing fields are detectable.
- Default unset 'updated' to 'created' when ordering by recency.
- Audit which custom datetime fields can legitimately be empty in your instance.
When it happens
Trigger: ParseTimestamp("") is called — i.e. the Jira issue JSON had an empty/missing timestamp field (e.g. updated, created, or a custom field) passed through directly.
Common situations: Jira fields that are legitimately unset (issue never updated in some views, empty custom datetime field); JSON unmarshaling into a string field that was null; older Jira Server versions omitting fields the Cloud API returns; mapping code not checking for null before calling ParseTimestamp.
Related errors
- unrecognized timestamp format: %s
- parse Jira timestamp: %w
- parse %s: %w
- dolt version output is unparseable
- parsing batch input: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ba88f497a30d8ec9.
Report an issue: GitHub.