zed-industries/zed · error · RuntimeError
issue {number} has no created_at
Error message
issue {number} has no created_at What it means
Raised when parse_dt(issue['created_at']) returns None inside fetch_issue(). parse_dt returns None only for falsy input, so GitHub returned HTTP 200 with an issue object whose created_at is null or an empty string. A genuinely missing key would raise KeyError instead — this error specifically means the field was present but empty.
Source
Thrown at script/triage_project_sync.py:263
issue_type: str | None # e.g. "Bug", "Crash", "Meta", "Tracking", or None
is_pull_request: bool
comments: list[dict]
def parse_dt(s: str | None) -> datetime | None:
if not s:
return None
return datetime.fromisoformat(s.replace("Z", "+00:00"))
def fetch_issue(number: int) -> IssueData:
issue = rest_get(f"repos/{REPO}/issues/{number}")
if not isinstance(issue, dict):
raise RuntimeError(f"unexpected response for issue {number}")
comments = rest_get_paginated(f"repos/{REPO}/issues/{number}/comments")
created_at = parse_dt(issue["created_at"])
if created_at is None:
raise RuntimeError(f"issue {number} has no created_at")
issue_type = None
if isinstance(issue.get("type"), dict):
issue_type = issue["type"].get("name")
return IssueData(
number=number,
node_id=issue["node_id"],
title=issue["title"],
state=issue["state"],
closed_at=parse_dt(issue.get("closed_at")),
created_at=created_at,
reporter=issue["user"]["login"],
assignees=[a["login"] for a in (issue.get("assignees") or [])],
labels=[l["name"] for l in issue["labels"]],
issue_type=issue_type,
is_pull_request="pull_request" in issue,
comments=comments,
)
View on GitHub (pinned to bc538def45)
Solutions
- Re-run the sync — transient payload anomalies usually do not repeat for the same issue
- Dump the raw JSON for the failing issue number and confirm created_at is actually empty
- If persistent, check api.github.com status / GitHub Enterprise version and report the payload shape
Example fix
# before
created_at = parse_dt(issue["created_at"])
if created_at is None:
raise RuntimeError(f"issue {number} has no created_at")
# after (skip anomalous issues with visibility instead of aborting the sync)
created_at = parse_dt(issue.get("created_at"))
if created_at is None:
log(f"issue {number} has empty created_at; skipping", "WARN")
continue Defensive patterns
Strategy: validation
Validate before calling
# Validate the raw payload shape before building IssueData
issue = rest_get(f"repos/{REPO}/issues/{number}")
if not isinstance(issue.get("created_at"), str) or not issue["created_at"].strip():
log(f"issue {number} has empty created_at; skipping", "WARN")
continue Type guard
def has_created_at(payload: dict) -> bool:
value = payload.get("created_at")
return isinstance(value, str) and value.strip() != "" Try / catch
try:
data = fetch_issue(number)
except RuntimeError as error:
if "no created_at" in str(error):
log(f"skipping anomalous issue {number}", "WARN")
continue
raise Prevention
- Treat single-issue anomalies as skippable with a warning instead of fatal
- Log the raw payload for the failing number when this fires to distinguish null vs empty string
- Re-run transient failures before investigating — GitHub payload glitches are usually one-off
When it happens
Trigger: GET /repos/{REPO}/issues/{number} succeeds (200) but the body has "created_at": null or "" — a degraded or partially-truncated payload from GitHub, a caching proxy, or an Enterprise Server version with different behavior.
Common situations: Transient GitHub incident producing incomplete payloads; an HTTP cache serving a truncated body; GitHub Enterprise Server API contract drift; response body cut mid-transfer and parsed leniently.
Related errors
- No assignment event for {assignee} on issue #{issue_number}
- unexpected response for issue {number}
- GraphQL errors: {json.dumps(data['errors'])[:300]}
- GraphQL error: {result['errors']}
- GraphQL error: {result['errors']}
AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16).
Data as JSON: /api/errors/b64456763fee9480.
Report an issue: GitHub.