Carousel item overlaping

:backhand_index_pointing_right: Bug Description


1. Summary

We have a bug in the component carousel, this component come from the package @amazon-devices/kepler-ui-components:2.4.2

https://developer.amazon.com/docs/kepler-tv-api/carousel.htm

App Name: VIX
App Link on Amazon Appstore (found through Developer Console β†’ Actions column in App List β†’ View on Amazon.com):

Bug Severity
Select one that applies

  • Impacts operation of app
  • Blocks current development
  • Improvement suggestion
  • Issue with documentation (If selected, please share the doc link and describe the issue)
  • Other

2. Steps to Reproduce

  1. Start application
  2. Go to any carousel
  3. Do horizontal scroll fast until reach the last element.

3. Observed Behavior

Explain what actually happened, noting any discrepancies or malfunctions.

The next card loaded from a query is overlaping to the last card of the first batch.

4. Expected Behavior

Describe what you expected the SDK to do under normal operation.

The next batch must to load correctly without overlaping.

4.a Possible Root Cause & Temporary Workaround

Fill out anything you have tried. If you don’t know, N/A is acceptable

We try to fetch the info 4 items before the last item.

5. Logs or crash report

There aren't logs or crash

6. Environment

Please fill out the fields related to your bug below:

  • SDK Version: Active SDK Version: 0.22.6006
    Vega CLI Version: 1.2.18

  • App State: Foreground

  • OS Information: Please ssh into the device via vega exec vda shell (or kepler exec vda shell for v0.21 and earlier) and copy the output from cat /etc/os-release into the answer section below. Note, if you don’t have a simulator running or device attached, the command will respond with vda: no devices/emulators found

    BRANCH_CODE="TV Ship day60"
    BUILD_DESC="OS 1.1 (TV Ship day60/10564800)"
    BUILD_FINGERPRINT="1.0.56480.0(9a1d8dfa7da5d600)/10564800N:user/dev-keys"
    BUILD_VARIANT="user"
    BUILD_TAGS="dev-keys"
    BUILD_DATE="Tue Jan 13 06:19:11 UTC 2026"
    BUILD_TIMESTAMP="1768285151"
    VERSION_NUMBER="1402066480030"
    

7. Example Code Snippet / Screenshots / Screengrabs

Include any relevant code or component setup in React Native that can help reproduce the bug.

import React, {
  useState, useEffect, useMemo, useCallback,
} from 'react';
import { View } from 'react-native';

import ActivityIndicator from 'src/components/atoms/ActivityIndicator/ActivityIndicator';
import useQueryPagination from 'src/hooks/useQueryPagination/useQueryPagination';
import {
  ICarouselPagination,
  IPageInfo,
  IUiModuleEdge,
  IUiModuleEdgeContentEdgeNode,
  ModuleType,
  UiCarouselTreatment,
} from 'src/types';
import CarouselTitle from 'src/components/atoms/CarouselTitle/CarouselTitle';
import { VIDEO_CAROUSEL_CONTENTS } from 'src/api/graphql/queries';

import VideoCarousel from '../VideoCarousel/VideoCarousel';

import getStyles from './CarouselModule.styles';

interface ICarouselModuleProps extends IUiModuleEdge {
  moduleIndex: number;
  moduleType: ModuleType;
  getNext: () => void;
}

export interface ICardsState {
  state: IUiModuleEdgeContentEdgeNode[];
  pageInfo?: IPageInfo;
}

const PAGINATION_KEY = 'modulesPagination';
const PATH_TO_PAGE_INFO = 'videoCarouselContents';
const NEXT_PAGINATE_COUNT = 10;

/**
 *  Carousel Module component
 *
 * @param props - CarouselModule props
 * @param props.node - Module node information
 * @param props.moduleIndex - Module index
 * @param props.moduleType - To see the type of carousel
 * @param props.getNext - getNext page
 * @returns - CarouselModule component
 */
function CarouselModule({
  node,
  moduleIndex,
  moduleType = ModuleType.videoCarousel,
  getNext,
}: ICarouselModuleProps): JSX.Element | null {
  const styles = useMemo(() => getStyles(), []);

  const {
    title, id, trackingMetadataJson,
  } = node;
  const { edges = [], pageInfo } = node.contents;
  const edgeNodes = useMemo(() => edges?.map((edge) => edge.node), [edges]);

  // this is to set carousel module when it is video carousel
  const [cardsState, setCardsState] = useState<ICardsState>({ state: edgeNodes, pageInfo });

  useEffect(() => {
    // this effect is to update recommended for you carousel (not video carousel)
    if (edges.length > 0 && moduleType !== ModuleType.videoCarousel) {
      setCardsState({ state: edgeNodes, pageInfo });
    }
  }, [edgeNodes, pageInfo, moduleType, edges.length]);

  const { fetchNextPage, data, isFetchingMore } = useQueryPagination(
    {
      queryKey: `carouselModulePagination:${id}`,
      query: VIDEO_CAROUSEL_CONTENTS,
      variablesQuery: { carouselId: id },
      nextCount: NEXT_PAGINATE_COUNT,
      paginationKey: PAGINATION_KEY,
      pathToPageInfo: PATH_TO_PAGE_INFO,
      isEnabled: moduleType === ModuleType.videoCarousel,
    },
  );

  const callPaginationQuery = useCallback((): void => {
    if (isFetchingMore) return;

    if (moduleType === ModuleType.videoCarousel) {
      if (cardsState.pageInfo?.hasNextPage) {
        fetchNextPage();
      }
    } else if (cardsState.state.length > 4) {
      getNext();
    }
  }, [fetchNextPage, getNext, isFetchingMore, moduleType, cardsState.pageInfo, cardsState.state.length]);

  useEffect(() => {
    if ((data !== undefined && moduleType !== ModuleType.continueWatchingCarousel) && data.pages.length > 1) {
      const pagesLength = data.pages.length - 1;
      const lastPage = data.pages[pagesLength] as ICarouselPagination;
      const lastEdges = lastPage.videoCarouselContents?.edges ?? [];
      const lastPageInfo = lastPage.videoCarouselContents?.pageInfo;
      const newItems = lastEdges.map((edge) => edge.node);

      setCardsState((prevState) => ({
        state: [...prevState.state, ...newItems],
        pageInfo: lastPageInfo,
      }));
    }
  }, [data, moduleType]);

  return (
    <View style={styles.carousel}>
      <CarouselTitle title={title} />
      {cardsState && (
        <>
          <VideoCarousel
            cards={cardsState.state}
            trackingMetadataJson={trackingMetadataJson}
            moduleType={node.moduleType}
            moduleIndex={moduleIndex}
            treatment={UiCarouselTreatment.LANDSCAPE}
            callPaginationQuery={callPaginationQuery}
            sportsEventCarouselType={node.sportsEventCarouselType}
            cellsPerRequest={NEXT_PAGINATE_COUNT}
            totalCount={node?.contents?.totalCount ?? 8}
          />
          {isFetchingMore && <ActivityIndicator />}
        </>

      )}
    </View>
  );
}

export default CarouselModule;


Additionally please provide the following if possible
Provide Screenshots / Screengrabs / Logs. Please include as much information as you can that will help debug.

Hello @Mariela_Hernandez

Thank you for the detailed report.
Kindly allow me some time to properly look into this and come back to you with updates.

In the meantime please help me with your app ASIN/Url.

Warm regards,
Ivy