{"record":{"id":"9b4ecaa726f6f7f0","repo":"yikart/AiToEarn","slug":"channelpaginationdirectionnotsupported","errorCode":"ChannelPaginationDirectionNotSupported","errorMessage":"ChannelPaginationDirectionNotSupported","messagePattern":"ChannelPaginationDirectionNotSupported","errorType":"error_code","errorClass":"AppException","httpStatus":null,"severity":"error","filePath":"project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/platform-pagination.helper.ts","lineNumber":35,"sourceCode":"      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) {\n        throw new AppException(ResponseCode.ChannelPaginationPageSizeExceeded, {\n          platform,\n          pageSize,\n          maxPageSize: pageMetadata.maxPageSize,\n        })\n      }\n      return { page: normalized.page ?? 1, pageSize }\n    }","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/platform-pagination.helper.ts#L17-L53","documentation":"normalizeChannelPagination validates cursor-based pagination inputs against a platform's pagination metadata. When the caller asks for ChannelPaginationDirection.Previous but the platform's cursor metadata declares supportsPrevious=false, the helper throws ChannelPaginationDirectionNotSupported because that platform can only paginate forward. The thrown AppException carries the platform and requested direction in its details.","triggerScenarios":"Calling any paginated channel listing API (works, comments, etc.) with direction: ChannelPaginationDirection.Previous (or 'previous' in the request body) for a platform whose ChannelPaginationMetadata has { mode: Cursor, supportsPrevious: false }. normalizeChannelPagination is invoked by input/normalizedPagination when a cursor or direction is present in the request.","commonSituations":"A frontend 'back to previous page' button applied to every platform; code shared across platforms where one platform (e.g. one that only offers forward cursors) rejects the backward navigation the other platforms support; reusing a saved 'Previous' direction from a different platform's list.","solutions":["Check the platform's pagination metadata (cursorMetadata.supportsPrevious) before offering backward pagination, and hide/disable the 'previous' control when it is false.","Omit the direction field so it defaults to ChannelPaginationDirection.Next and paginate forward from the start.","Implement client-side backward navigation by keeping a stack of cursors and using the previous cursor with direction Next, instead of requesting direction Previous.","If the platform genuinely supports backward cursors, fix the integration registration so cursorMetadata.supportsPrevious is true."],"exampleFix":"// before\nawait listComments(accountId, { cursor, direction: ChannelPaginationDirection.Previous })\n// after\nconst meta = getPlatformPaginationMetadata(platform)\nconst direction = meta.mode === ChannelPaginationMode.Cursor && meta.supportsPrevious\n  ? ChannelPaginationDirection.Previous\n  : ChannelPaginationDirection.Next\nawait listComments(accountId, { cursor, direction })","handlingStrategy":"validation","validationCode":"const meta = platformPaginationMetadata[platform]\nconst canGoPrevious = meta?.mode === ChannelPaginationMode.Cursor && meta.supportsPrevious\nif (requested.direction === ChannelPaginationDirection.Previous && !canGoPrevious) {\n  // use Next or disable backward paging\n}","typeGuard":"function supportsPreviousPagination(meta: ChannelPaginationMetadata): meta is Extract<ChannelPaginationMetadata, { mode: ChannelPaginationMode.Cursor; supportsPrevious: true }> {\n  return meta.mode === ChannelPaginationMode.Cursor && meta.supportsPrevious\n}","tryCatchPattern":"try {\n  return await listItems({ cursor, direction })\n} catch (e) {\n  if (e instanceof AppException && e.code === ResponseCode.ChannelPaginationDirectionNotSupported) {\n    return await listItems({ cursor: previousCursorStack.pop(), direction: ChannelPaginationDirection.Next })\n  }\n  throw e\n}","preventionTips":["Read the platform's pagination metadata before building list UI controls.","Only render a 'previous page' button when supportsPrevious is true.","Keep a client-side cursor stack for backward navigation on forward-only platforms.","Never reuse direction values across platforms without checking capability."],"tags":["pagination","cursor","platform-capability","validation"],"backgroundTag":"pagination-direction-not-supported","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}