{"record":{"id":"47449fe0c96bd755","repo":"gastownhall/beads","slug":"parse-updated-at-w","errorCode":null,"errorMessage":"parse updated_at: %w","messagePattern":"parse updated_at: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/notion/mapping.go","lineNumber":91,"sourceCode":"\tif config == nil {\n\t\tconfig = DefaultMappingConfig()\n\t}\n\n\tstatus := statusToBeads(issue.Status, config)\n\tpriority := priorityToBeads(issue.Priority, config)\n\tissueTypeRaw := issue.IssueType\n\tif strings.TrimSpace(issueTypeRaw) == \"\" {\n\t\tissueTypeRaw = issue.Type\n\t}\n\tissueType := typeToBeads(issueTypeRaw, config)\n\n\tcreatedAt, hasCreated, err := parseMappingTimestamp(string(issue.CreatedAt))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"parse created_at: %w\", err)\n\t}\n\tupdatedAt, hasUpdated, err := parseMappingTimestamp(string(issue.UpdatedAt))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"parse updated_at: %w\", err)\n\t}\n\tnow := time.Now().UTC()\n\tif !hasCreated {\n\t\tcreatedAt = now\n\t}\n\tif !hasUpdated {\n\t\tupdatedAt = createdAt\n\t}\n\n\tbeadsIssue := &types.Issue{\n\t\tID:           strings.TrimSpace(issue.ID),\n\t\tTitle:        strings.TrimSpace(issue.Title),\n\t\tDescription:  strings.TrimSpace(issue.Description),\n\t\tStatus:       status,\n\t\tPriority:     priority,\n\t\tIssueType:    issueType,\n\t\tAssignee:     issue.Assignee,\n\t\tLabels:       append([]string(nil), issue.Labels...),","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/notion/mapping.go#L73-L109","documentation":"Same class as the created_at failure but for the UpdatedAt field: parseMappingTimestamp rejected the string. Happens after created_at parsed successfully, so the issue is specific to the updated_at value. An empty/absent value is fine (hasUpdated=false, falls back to now), only a non-empty unparseable string errors.","triggerScenarios":"UpdatedAt formatted differently from CreatedAt in the source data (mixed exporters); sentinel strings like 'never' or 'n/a' in the updated field; epoch numbers as strings; timestamps with fractional seconds beyond the accepted layouts.","commonSituations":"Different tools writing created vs updated fields with different precision; hand-edited JSON exports; migrations from another tracker leaving '0' or '-' in updated_at; Notion last_edited_time exported with a layout the mapping doesn't expect.","solutions":["Inspect the wrapped time.ParseError to see the exact bad value.","Normalize both created_at and updated_at to the same RFC3339 format in the exporter.","Omit or null the field when unknown so the mapping falls back to time.Now().","Add a preprocessing step that validates timestamps with time.Parse before calling BeadsIssueFromPullIssue."],"exampleFix":"// before\nissue.UpdatedAt = \"never\" // unparseable\nbead, err := BeadsIssueFromPullIssue(issue, config) // parse updated_at error\n\n// after\nif updated, err := time.Parse(time.RFC3339, raw); err == nil {\n    issue.UpdatedAt = types.String(updated.UTC().Format(time.RFC3339))\n} else {\n    issue.UpdatedAt = types.String(\"\") // falls back to now\n}","handlingStrategy":"validation","validationCode":"if _, err := time.Parse(time.RFC3339, updatedAt); err != nil {\n    return fmt.Errorf(\"invalid updated_at %q: %w\", updatedAt, err)\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"parse updated_at\") {\n    log.Printf(\"bad updated_at value from source: %v\", err)\n}","preventionTips":["Use the same timestamp format for created_at and updated_at in exporters.","Scrub sentinel values ('never', '0', '-') to null before mapping.","Round-trip test exports through BeadsIssueFromPullIssue to catch format drift."],"tags":["notion","mapping","timestamp","parse-error"],"backgroundTag":"timestamp-parse-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}