{"record":{"id":"1f04204e8247fa7b","repo":"yikart/AiToEarn","slug":"channelpaginationlimitexceeded","errorCode":"ChannelPaginationLimitExceeded","errorMessage":"ChannelPaginationLimitExceeded","messagePattern":"ChannelPaginationLimitExceeded","errorType":"error_code","errorClass":"AppException","httpStatus":null,"severity":"warning","filePath":"project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/platform-pagination.helper.ts","lineNumber":27,"sourceCode":"  pagination: ChannelPaginationInput,\n): ChannelPaginationInput {\n  const normalized = getDefaultPagination(metadata, pagination)\n  const normalizedMode = getPaginationInputMode(normalized)\n\n  if (metadata.mode !== normalizedMode) {\n    throw new AppException(ResponseCode.ChannelPaginationModeNotSupported, {\n      platform,\n      expectedMode: metadata.mode,\n      actualMode: normalizedMode,\n    })\n  }\n\n  switch (normalizedMode) {\n    case ChannelPaginationMode.Cursor: {\n      const cursorMetadata = metadata as Extract<ChannelPaginationMetadata, { mode: ChannelPaginationMode.Cursor }>\n      const limit = normalized.limit ?? cursorMetadata.defaultLimit\n      if (limit > cursorMetadata.maxLimit) {\n        throw new AppException(ResponseCode.ChannelPaginationLimitExceeded, {\n          platform,\n          limit,\n          maxLimit: cursorMetadata.maxLimit,\n        })\n      }\n      const direction = normalized.direction ?? ChannelPaginationDirection.Next\n      if (direction === ChannelPaginationDirection.Previous && !cursorMetadata.supportsPrevious) {\n        throw new AppException(ResponseCode.ChannelPaginationDirectionNotSupported, {\n          platform,\n          direction,\n        })\n      }\n      return { ...normalized, limit, direction }\n    }\n    case ChannelPaginationMode.Page: {\n      const pageMetadata = metadata as Extract<ChannelPaginationMetadata, { mode: ChannelPaginationMode.Page }>\n      const pageSize = normalized.pageSize ?? pageMetadata.defaultPageSize\n      if (pageSize > pageMetadata.maxPageSize) {","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/platform-pagination.helper.ts#L9-L45","documentation":"ChannelPaginationLimitExceeded is thrown by normalizeChannelPagination when a cursor-mode pagination request's limit exceeds the platform's declared maxLimit. It guards against sending page sizes the upstream platform API would reject.","triggerScenarios":"Calling normalizeChannelPagination with Cursor-mode metadata where (normalized.limit ?? cursorMetadata.defaultLimit) > cursorMetadata.maxLimit — e.g. requesting limit=100 against a platform whose maxLimit is 50.","commonSituations":"Clients with hardcoded large page sizes; UI 'load all' buttons clamping limits incorrectly; a platform lowering its max limit after an API version change while callers kept old values.","solutions":["Clamp the limit to cursorMetadata.maxLimit before calling","Omit limit to use the platform's defaultLimit","Update client page-size presets to respect each platform's declared max"],"exampleFix":"// before\nnormalizeChannelPagination(platform, cursorMeta, { cursor, limit: 100 }) // maxLimit 50 -> throws\n// after\nconst limit = Math.min(requestedLimit, cursorMeta.maxLimit)\nnormalizeChannelPagination(platform, cursorMeta, { cursor, limit })","handlingStrategy":"validation","validationCode":"function clampLimit(limit: number | undefined, meta: { defaultLimit: number; maxLimit: number }): number {\n  return Math.min(limit ?? meta.defaultLimit, meta.maxLimit)\n}\nconst safePagination = { ...input, limit: clampLimit(input.limit, cursorMeta) }","typeGuard":"function isWithinLimit(limit: number | undefined, meta: { defaultLimit: number; maxLimit: number }): boolean {\n  return (limit ?? meta.defaultLimit) <= meta.maxLimit\n}","tryCatchPattern":"try {\n  const page = await listChannelWorks(channelId, pagination)\n} catch (e) {\n  if (e instanceof AppException && e.code === ResponseCode.ChannelPaginationLimitExceeded) {\n    const max = (e.context as { maxLimit: number }).maxLimit\n    page = await listChannelWorks(channelId, { ...pagination, limit: max })\n  } else throw e\n}","preventionTips":["Clamp page sizes to the platform's declared maxLimit","Use defaultLimit when no explicit page size is needed","Track per-platform max limits in client config and update on API version changes"],"tags":["pagination","limits","input-validation"],"backgroundTag":"pagination-limit-exceeded","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}