{"record":{"id":"bd6e75ade437f8e3","repo":"matryer/xbar","slug":"time-parse-created-at","errorCode":null,"errorMessage":"time.Parse: created_at","messagePattern":"time\\.Parse: created_at","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/update/update.go","lineNumber":134,"sourceCode":"\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"get latest release\")\n\t}\n\tdefer resp.Body.Close()\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, errors.Errorf(\"failed to check for updates: got %s\", resp.Status)\n\t}\n\tb, err := io.ReadAll(io.LimitReader(resp.Body, u.DownloadBytesLimit))\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"read body\")\n\t}\n\tvar latestRelease Release\n\terr = json.Unmarshal(b, &latestRelease)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"marshal\")\n\t}\n\tlatestRelease.CreatedAt, err = time.Parse(time.RFC3339Nano, latestRelease.CreatedAtString)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"time.Parse: created_at\")\n\t}\n\treturn &latestRelease, nil\n}\n\n// HasUpdate checks whether there's an update or not.\nfunc (u *Updater) HasUpdate() (*Release, bool, error) {\n\tlatest, err := u.getLatestRelease()\n\tif err != nil {\n\t\treturn nil, false, err\n\t}\n\thasUpdate := hasUpdate(u.CurrentVersion, latest.TagName)\n\treturn latest, hasUpdate, nil\n}\n\n// hasUpdate compares the current and latest version strings to\n// see if there is an update.\n// Returns false if the versions match.\n// Returns false is current is in front of latest.","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/matryer/xbar/blob/d624239058997c80118eaebe2e7f8331b3c765e0/pkg/update/update.go#L116-L152","documentation":"This error wraps a failure to parse the GitHub release's `created_at` timestamp. The updater fetches release metadata as JSON (where the timestamp is a raw string field `CreatedAtString`) and then parses it with time.Parse(time.RFC3339Nano, ...). If the GitHub API returns a timestamp in a different format, an empty string, or malformed JSON content in that field, parsing fails and the error is wrapped as 'time.Parse: created_at'.","triggerScenarios":"Calling Update() or HasUpdate() when the release JSON returned from the GitHub API contains a created_at value that is not valid RFC3339Nano (e.g. empty string, 'null', or a non-RFC3339 date format from a proxy/mirror of the GitHub API).","commonSituations":"Hitting a self-hosted or rate-limited/proxied GitHub API endpoint that returns timestamps in a different layout; a release created via API with a manually-set malformed created_at; network middleware returning stub/empty JSON bodies (e.g. mocks in tests without created_at set).","solutions":["Verify the endpoint returns real GitHub release JSON with a valid RFC3339 created_at (curl the /releases/latest URL and inspect created_at).","If using a proxy or mirror, normalize the created_at field to RFC3339/RFC3339Nano before the updater reads it.","Ensure your client/auth is not causing GitHub to return an error page or stub body instead of release JSON.","As a fallback, patch the parsing call site to tolerate missing timestamps (leave CreatedAt zero-valued instead of failing)."],"exampleFix":"// before\nlatestRelease.CreatedAt, err = time.Parse(time.RFC3339Nano, latestRelease.CreatedAtString)\nif err != nil {\n\treturn nil, errors.Wrap(err, \"time.Parse: created_at\")\n}\n// after\nif latestRelease.CreatedAtString != \"\" {\n\tt, perr := time.Parse(time.RFC3339Nano, latestRelease.CreatedAtString)\n\tif perr == nil {\n\t\tlatestRelease.CreatedAt = t\n\t}\n}","handlingStrategy":"validation","validationCode":"if rel.CreatedAtString == \"\" || rel.CreatedAtString == \"null\" {\n\treturn errors.New(\"release has no created_at timestamp\")\n}\nif _, err := time.Parse(time.RFC3339Nano, rel.CreatedAtString); err != nil {\n\treturn fmt.Errorf(\"bad created_at %q: %w\", rel.CreatedAtString, err)\n}","typeGuard":"func validRFC3339(s string) bool {\n\t_, err := time.Parse(time.RFC3339Nano, s)\n\treturn err == nil\n}","tryCatchPattern":"rel, err := u.HasUpdate()\nif err != nil {\n\tif strings.Contains(err.Error(), \"time.Parse: created_at\") {\n\t\tlog.Printf(\"ignoring bad release timestamp: %v\", err)\n\t\treturn nil\n\t}\n\treturn err\n}","preventionTips":["Hit a real GitHub API endpoint, not a proxy that rewrites timestamps","Don't stub created_at in test fixtures without RFC3339 formatting","Verify API responses with curl before debugging the parser"],"tags":["time-parsing","json","github-api"],"backgroundTag":"time-parse-failed","analyzedSha":"d624239058997c80118eaebe2e7f8331b3c765e0","analyzedAt":"2026-09-02T22:38:22.007Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}