{"record":{"id":"e5bebe298275a3ab","repo":"mattermost-community/focalboard","slug":"cannot-parse-datetime-s-for-board-members-histo","errorCode":null,"errorMessage":"cannot parse datetime '%s' for board_members_history scan: %w","messagePattern":"cannot parse datetime '(.+?)' for board_members_history scan: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/services/store/sqlstore/board.go","lineNumber":183,"sourceCode":"\n\t\terr := rows.Scan(\n\t\t\t&boardMemberHistoryEntry.BoardID,\n\t\t\t&boardMemberHistoryEntry.UserID,\n\t\t\t&boardMemberHistoryEntry.Action,\n\t\t\t&insertAt,\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// parse the insert_at timestamp which is different based on database type.\n\t\tdateTemplate := \"2006-01-02T15:04:05Z0700\"\n\t\tif s.dbType == model.MysqlDBType {\n\t\t\tdateTemplate = \"2006-01-02 15:04:05.000000\"\n\t\t}\n\t\tts, err := time.Parse(dateTemplate, insertAt.String)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"cannot parse datetime '%s' for board_members_history scan: %w\", insertAt.String, err)\n\t\t}\n\t\tboardMemberHistoryEntry.InsertAt = ts\n\n\t\tboardMemberHistoryEntries = append(boardMemberHistoryEntries, &boardMemberHistoryEntry)\n\t}\n\n\treturn boardMemberHistoryEntries, nil\n}\n\nfunc (s *SQLStore) getBoardByCondition(db sq.BaseRunner, conditions ...interface{}) (*model.Board, error) {\n\tboards, err := s.getBoardsByCondition(db, conditions...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn boards[0], nil\n}\n","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/mattermost-community/focalboard/blob/a84bbb65e32edf972856b329417096ac413518e9/server/services/store/sqlstore/board.go#L165-L201","documentation":"boardMemberHistoryEntriesFromRows parses the insert_at column of board_members_history rows into time.Time using a dialect-specific layout; when time.Parse fails on the string value, this error wraps the unparseable value and the underlying error. It means the database returned insert_at in an unexpected textual format.","triggerScenarios":"getBoardMemberHistory scanning rows where insert_at's string doesn't match '2006-01-02 15:04:05.000000' (MySQL) or '2006-01-02T15:04:05Z0700' (Postgres/SQLite) — e.g. a driver returning a different formatting or zero-time representation.","commonSituations":"MySQL servers/drivers configured with different datetime precision or strict formatting; using an alternate driver that formats DATETIME differently; reading history rows written by another tool/version with a different timestamp format; locale/timezone formatting leaks from custom DB settings.","solutions":["Check the quoted datetime in the error to see the actual format returned and compare with the expected template","Verify the MySQL driver version (e.g. go-sql-driver/mysql) returns DATETIME as '2006-01-02 15:04:05.000000'; add parseTime/loc DSN params if needed","Ensure rows were written by Focalboard itself (not imported with foreign timestamp formats)","If the driver can't be changed, patch the dateTemplate to match your DB's output format"],"exampleFix":"// before\ndateTemplate := \"2006-01-02T15:04:05Z0700\"\nif s.dbType == model.MysqlDBType {\n    dateTemplate = \"2006-01-02 15:04:05.000000\"\n}\n// after\ndateTemplate := \"2006-01-02T15:04:05Z0700\"\nif s.dbType == model.MysqlDBType {\n    dateTemplate = \"2006-01-02 15:04:05.999999\" // tolerate rows without fractional seconds\n}\n","handlingStrategy":"validation","validationCode":"func isExpectedDatetimeFormat(s string, dbType string) bool {\n    layout := \"2006-01-02T15:04:05Z0700\"\n    if dbType == \"mysql\" {\n        layout = \"2006-01-02 15:04:05.000000\"\n    }\n    _, err := time.Parse(layout, s)\n    return err == nil\n}","typeGuard":null,"tryCatchPattern":"entries, err := store.GetBoardMemberHistory(boardID)\nif err != nil && strings.Contains(err.Error(), \"cannot parse datetime\") {\n    log.Printf(\"unexpected insert_at format from DB: %v\", err)\n    return fmt.Errorf(\"driver/DB timestamp format mismatch: %w\", err)\n}","preventionTips":["Use the supported MySQL driver with parseTime configured as the server expects","Avoid external tools writing board_members_history rows with foreign timestamp formats","Keep DB datetime column types/precision unchanged across migrations","If your driver formats differently, align the dateTemplate with actual output"],"tags":["datetime","parsing","mysql","database"],"backgroundTag":"datetime-parse-failed","analyzedSha":"a84bbb65e32edf972856b329417096ac413518e9","analyzedAt":"2026-08-30T09:22:20.720Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}