{"record":{"id":"cfbcd3550ba3d640","repo":"toeverything/AFFiNE","slug":"bad-request-cfbcd3","errorCode":"bad_request","errorMessage":"Invalid pagination cursor","messagePattern":"Invalid pagination cursor","errorType":"exception","errorClass":"BadRequest","httpStatus":400,"severity":"warning","filePath":"packages/backend/server/src/models/workspace-analytics.ts","lineNumber":220,"sourceCode":"      return decodeWithJson<T>(raw);\n    } catch {\n      throw new BadRequest('Invalid pagination cursor');\n    }\n  }\n}\n\nfunction parseCursorDate(value: unknown): Date {\n  if (\n    typeof value !== 'string' &&\n    typeof value !== 'number' &&\n    !(value instanceof Date)\n  ) {\n    throw new BadRequest('Invalid pagination cursor');\n  }\n\n  const parsed = new Date(value);\n  if (Number.isNaN(parsed.getTime())) {\n    throw new BadRequest('Invalid pagination cursor');\n  }\n  return parsed;\n}\n\nfunction parseCursorNumber(value: unknown): number {\n  const parsed = Number(value);\n  if (!Number.isFinite(parsed)) {\n    throw new BadRequest('Invalid pagination cursor');\n  }\n  return parsed;\n}\n\nfunction parseCursorString(value: unknown): string {\n  if (typeof value !== 'string' || !value) {\n    throw new BadRequest('Invalid pagination cursor');\n  }\n  return value;\n}","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/packages/backend/server/src/models/workspace-analytics.ts#L202-L238","documentation":"Thrown by parseCursorDate (workspace-analytics.ts:220) when new Date(value) returns an Invalid Date (getTime() is NaN) — the value was the right type but did not parse to a real date. UserFriendlyError BadRequest, code bad_request, HTTP 400.","triggerScenarios":"A cursor date field that is a string like \"not-a-date\" or a malformed/truncated ISO string, or a number that is not a valid epoch timestamp.","commonSituations":"Truncated ISO string in a cached cursor; locale-formatted date slipped in; non-numeric garbage typed into the field; stale cursor across a format change.","solutions":["Restart pagination from page 1 to regenerate the cursor.","Ensure cursors originate only from server responses.","Validate/normalize date strings before persisting them."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function isValidCursorDate(v: unknown): boolean {\n  if (typeof v !== 'string' && typeof v !== 'number' && !(v instanceof Date)) return false;\n  return !Number.isNaN(new Date(v).getTime());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate that date fields parse to real dates before sending.","Drop and restart from page 1 on an unparseable date cursor.","Only forward server-issued cursors unchanged."],"tags":["pagination","cursor","analytics","input-validation"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}