diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
index 73a255f392befa57bdd71dd3495a20d65db004f7..747d94d92f2f147183af1dad32448093303fcec7 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
@@ -16,6 +16,9 @@ import { TRACKING_CATEGORIES } from '../../constants';
 export const i18n = {
   downloadArtifacts: __('Download artifacts'),
   artifactsFetchErrorMessage: s__('Pipelines|Could not load artifacts.'),
+  artifactsFetchWarningMessage: s__(
+    'Pipelines|Failed to update. Please reload page to update the list of artifacts.',
+  ),
   emptyArtifactsMessage: __('No artifacts found'),
 };
 
@@ -52,6 +55,7 @@ export default {
       hasError: false,
       isLoading: false,
       searchQuery: '',
+      isNewPipeline: false,
     };
   },
   computed: {
@@ -64,13 +68,24 @@ export default {
         : this.artifacts;
     },
   },
+  watch: {
+    pipelineId() {
+      this.isNewPipeline = true;
+    },
+  },
   methods: {
     fetchArtifacts() {
       // refactor tracking based on action once this dropdown supports
       // actions other than artifacts
       this.track('click_artifacts_dropdown', { label: TRACKING_CATEGORIES.table });
 
+      // Preserve the last good list and present it if a request fails
+      const oldArtifacts = [...this.artifacts];
+      this.artifacts = [];
+
+      this.hasError = false;
       this.isLoading = true;
+
       // Replace the placeholder with the ID of the pipeline we are viewing
       const endpoint = this.artifactsEndpoint.replace(
         this.artifactsEndpointPlaceholder,
@@ -80,9 +95,13 @@ export default {
         .get(endpoint)
         .then(({ data }) => {
           this.artifacts = data.artifacts;
+          this.isNewPipeline = false;
         })
         .catch(() => {
           this.hasError = true;
+          if (!this.isNewPipeline) {
+            this.artifacts = oldArtifacts;
+          }
         })
         .finally(() => {
           this.isLoading = false;
@@ -108,10 +127,10 @@ export default {
     right
     lazy
     text-sr-only
-    @show.once="fetchArtifacts"
+    @show="fetchArtifacts"
     @shown="handleDropdownShown"
   >
-    <gl-alert v-if="hasError" variant="danger" :dismissible="false">
+    <gl-alert v-if="hasError && !hasArtifacts" variant="danger" :dismissible="false">
       {{ $options.i18n.artifactsFetchErrorMessage }}
     </gl-alert>
 
@@ -136,5 +155,18 @@ export default {
     >
       {{ artifact.name }}
     </gl-dropdown-item>
+
+    <template #footer>
+      <gl-dropdown-item
+        v-if="hasError && hasArtifacts"
+        class="gl-list-style-none"
+        disabled
+        data-testid="artifacts-fetch-warning"
+      >
+        <span class="gl-font-sm">
+          {{ $options.i18n.artifactsFetchWarningMessage }}
+        </span>
+      </gl-dropdown-item>
+    </template>
   </gl-dropdown>
 </template>
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 8a5a9b38db10bca6c5a82986bbc53d992a554944..f5df003e171045aee580c9a622d30d46a35e814f 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -34399,6 +34399,9 @@ msgstr ""
 msgid "Pipelines|Editor"
 msgstr ""
 
+msgid "Pipelines|Failed to update. Please reload page to update the list of artifacts."
+msgstr ""
+
 msgid "Pipelines|Follow these instructions to install GitLab Runner on macOS."
 msgstr ""
 
diff --git a/spec/frontend/pipelines/pipeline_multi_actions_spec.js b/spec/frontend/pipelines/pipeline_multi_actions_spec.js
index 43336bbc7484d93c7d57e22c3fe05df2b0440bc9..0fdc45a5931cce4f9d09cba7e19ba2e682805ad3 100644
--- a/spec/frontend/pipelines/pipeline_multi_actions_spec.js
+++ b/spec/frontend/pipelines/pipeline_multi_actions_spec.js
@@ -28,6 +28,20 @@ describe('Pipeline Multi Actions Dropdown', () => {
       path: '/download/path-two',
     },
   ];
+  const newArtifacts = [
+    {
+      name: 'job-3 my-new-artifact',
+      path: '/new/download/path',
+    },
+    {
+      name: 'job-4 my-new-artifact-2',
+      path: '/new/download/path-two',
+    },
+    {
+      name: 'job-5 my-new-artifact-3',
+      path: '/new/download/path-three',
+    },
+  ];
   const artifactItemTestId = 'artifact-item';
   const artifactsEndpointPlaceholder = ':pipeline_artifacts_id';
   const artifactsEndpoint = `endpoint/${artifactsEndpointPlaceholder}/artifacts.json`;
@@ -59,8 +73,15 @@ describe('Pipeline Multi Actions Dropdown', () => {
   const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
   const findAllArtifactItems = () => wrapper.findAllByTestId(artifactItemTestId);
   const findFirstArtifactItem = () => wrapper.findByTestId(artifactItemTestId);
+  const findAllArtifactItemsData = () =>
+    wrapper.findAllByTestId(artifactItemTestId).wrappers.map((x) => ({
+      path: x.attributes('href'),
+      name: x.text(),
+    }));
   const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
   const findEmptyMessage = () => wrapper.findByTestId('artifacts-empty-message');
+  const findWarning = () => wrapper.findByTestId('artifacts-fetch-warning');
+  const changePipelineId = (newId) => wrapper.setProps({ pipelineId: newId });
 
   beforeEach(() => {
     mockAxios = new MockAdapter(axios);
@@ -136,6 +157,80 @@ describe('Pipeline Multi Actions Dropdown', () => {
           expect(findFirstArtifactItem().attributes('href')).toBe(artifacts[0].path);
           expect(findFirstArtifactItem().text()).toBe(artifacts[0].name);
         });
+
+        describe('when opened again with new artifacts', () => {
+          describe('with a successful refetch', () => {
+            beforeEach(async () => {
+              mockAxios.resetHistory();
+              mockAxios.onGet(endpoint).replyOnce(HTTP_STATUS_OK, { artifacts: newArtifacts });
+
+              findDropdown().vm.$emit('show');
+              await nextTick();
+            });
+
+            it('should hide list and render a loading spinner on dropdown click', () => {
+              expect(findAllArtifactItems()).toHaveLength(0);
+              expect(findLoadingIcon().exists()).toBe(true);
+            });
+
+            it('should not render warning or empty message while loading', () => {
+              expect(findEmptyMessage().exists()).toBe(false);
+              expect(findWarning().exists()).toBe(false);
+            });
+
+            it('should render the correct new list', async () => {
+              await waitForPromises();
+
+              expect(findAllArtifactItemsData()).toEqual(newArtifacts);
+            });
+          });
+
+          describe('with a failing refetch', () => {
+            beforeEach(async () => {
+              mockAxios.onGet(endpoint).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR);
+
+              findDropdown().vm.$emit('show');
+              await waitForPromises();
+            });
+
+            it('should render warning', () => {
+              expect(findWarning().text()).toBe(i18n.artifactsFetchWarningMessage);
+            });
+
+            it('should render old list', () => {
+              expect(findAllArtifactItemsData()).toEqual(artifacts);
+            });
+          });
+        });
+
+        describe('pipeline id has changed', () => {
+          const newEndpoint = artifactsEndpoint.replace(
+            artifactsEndpointPlaceholder,
+            pipelineId + 1,
+          );
+
+          beforeEach(() => {
+            changePipelineId(pipelineId + 1);
+          });
+
+          describe('followed by a failing request', () => {
+            beforeEach(async () => {
+              mockAxios.onGet(newEndpoint).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR);
+
+              findDropdown().vm.$emit('show');
+              await waitForPromises();
+            });
+
+            it('should render error message and no warning', () => {
+              expect(findWarning().exists()).toBe(false);
+              expect(findAlert().text()).toBe(i18n.artifactsFetchErrorMessage);
+            });
+
+            it('should clear list', () => {
+              expect(findAllArtifactItems()).toHaveLength(0);
+            });
+          });
+        });
       });
 
       describe('artifacts list is empty', () => {