diff --git a/scripts/langindex.json b/scripts/langindex.json
index df750b6bf..5aa09b9f6 100644
--- a/scripts/langindex.json
+++ b/scripts/langindex.json
@@ -1497,6 +1497,7 @@
   "core.course.insufficientavailablequota": "local_moodlemobileapp",
   "core.course.insufficientavailablespace": "local_moodlemobileapp",
   "core.course.manualcompletionnotsynced": "local_moodlemobileapp",
+  "core.course.modulenotfound": "local_moodlemobileapp",
   "core.course.nocontentavailable": "local_moodlemobileapp",
   "core.course.overriddennotice": "grades",
   "core.course.refreshcourse": "local_moodlemobileapp",
diff --git a/src/addons/mod/assign/services/assign.ts b/src/addons/mod/assign/services/assign.ts
index 8ebc66911..d55024c97 100644
--- a/src/addons/mod/assign/services/assign.ts
+++ b/src/addons/mod/assign/services/assign.ts
@@ -17,7 +17,7 @@ import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@
 import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
 import { CoreInterceptor } from '@classes/interceptor';
 import { CoreWSExternalWarning, CoreWSExternalFile, CoreWSFile } from '@services/ws';
-import { makeSingleton } from '@singletons';
+import { makeSingleton, Translate } from '@singletons';
 import { CoreCourseCommonModWSOptions } from '@features/course/services/course';
 import { CoreTextUtils } from '@services/utils/text';
 import { CoreGrades } from '@features/grades/services/grades';
@@ -218,7 +218,7 @@ export class AddonModAssignProvider {
             }
         }
 
-        throw new CoreError('Assignment not found');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/book/components/index/index.ts b/src/addons/mod/book/components/index/index.ts
index 9473a677c..6cad64def 100644
--- a/src/addons/mod/book/components/index/index.ts
+++ b/src/addons/mod/book/components/index/index.ts
@@ -14,9 +14,7 @@
 
 import { Component, Optional, Input, OnInit } from '@angular/core';
 import { IonContent } from '@ionic/angular';
-import {
-    CoreCourseModuleMainResourceComponent, CoreCourseResourceDownloadResult,
-} from '@features/course/classes/main-resource-component';
+import { CoreCourseModuleMainResourceComponent } from '@features/course/classes/main-resource-component';
 import {
     AddonModBookProvider,
     AddonModBookContentsMap,
@@ -130,35 +128,10 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
      * @return Promise resolved when done.
      */
     protected async fetchContent(refresh = false): Promise<void> {
-        const promises: Promise<void>[] = [];
-        let downloadResult: CoreCourseResourceDownloadResult | undefined;
-
-        // Try to get the book data. Ignore errors since this WS isn't available in some Moodle versions.
-        promises.push(CoreUtils.ignoreErrors(AddonModBook.getBook(this.courseId, this.module.id))
-            .then((book) => {
-                if (!book) {
-                    return;
-                }
-
-                this.book = book;
-                this.dataRetrieved.emit(book);
-
-                this.description = book.intro;
-                this.displayNavBar = book.navstyle != AddonModBookNavStyle.TOC_ONLY;
-                this.displayTitlesInNavBar = book.navstyle == AddonModBookNavStyle.TEXT;
-
-                return;
-            }));
-
-        // Get module status to determine if it needs to be downloaded.
-        promises.push(this.downloadResourceIfNeeded(refresh).then((result) => {
-            downloadResult = result;
-
-            return;
-        }));
-
         try {
-            await Promise.all(promises);
+            const downloadResult = await this.downloadResourceIfNeeded(refresh);
+
+            await this.loadBookData();
 
             this.contentsMap = AddonModBook.getContentsMap(this.module.contents);
             this.chapters = AddonModBook.getTocList(this.module.contents);
@@ -191,6 +164,21 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
         }
     }
 
+    /**
+     * Load book data from WS.
+     *
+     * @return Promise resolved when done.
+     */
+    protected async loadBookData(): Promise<void> {
+        this.book = await AddonModBook.getBook(this.courseId, this.module.id);
+
+        this.dataRetrieved.emit(this.book);
+
+        this.description = this.book.intro;
+        this.displayNavBar = this.book.navstyle != AddonModBookNavStyle.TOC_ONLY;
+        this.displayTitlesInNavBar = this.book.navstyle == AddonModBookNavStyle.TEXT;
+    }
+
     /**
      * Load a book chapter.
      *
diff --git a/src/addons/mod/book/services/book.ts b/src/addons/mod/book/services/book.ts
index d87e9e34e..cfdfdf680 100644
--- a/src/addons/mod/book/services/book.ts
+++ b/src/addons/mod/book/services/book.ts
@@ -17,7 +17,7 @@ import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites';
 import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
 import { CoreTagItem } from '@features/tag/services/tag';
 import { CoreWSExternalWarning, CoreWSExternalFile, CoreWS } from '@services/ws';
-import { makeSingleton } from '@singletons';
+import { makeSingleton, Translate } from '@singletons';
 import { CoreCourseLogHelper } from '@features/course/services/log-helper';
 import { CoreCourse, CoreCourseModuleContentFile } from '@features/course/services/course';
 import { CoreUtils } from '@services/utils/utils';
@@ -103,7 +103,7 @@ export class AddonModBookProvider {
             return book;
         }
 
-        throw new CoreError('Book not found');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/chat/services/chat.ts b/src/addons/mod/chat/services/chat.ts
index 2882cc6c1..12af031ca 100644
--- a/src/addons/mod/chat/services/chat.ts
+++ b/src/addons/mod/chat/services/chat.ts
@@ -61,7 +61,7 @@ export class AddonModChatProvider {
             return chat;
         }
 
-        throw new CoreError('Chat not found.');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/choice/services/choice.ts b/src/addons/mod/choice/services/choice.ts
index 8e6af5989..af256c9ee 100644
--- a/src/addons/mod/choice/services/choice.ts
+++ b/src/addons/mod/choice/services/choice.ts
@@ -23,7 +23,7 @@ import { CoreFilepool } from '@services/filepool';
 import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites';
 import { CoreUtils } from '@services/utils/utils';
 import { CoreStatusWithWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
-import { makeSingleton } from '@singletons';
+import { makeSingleton, Translate } from '@singletons';
 import { AddonModChoiceOffline } from './choice-offline';
 import { AddonModChoiceAutoSyncData, AddonModChoiceSyncProvider } from './choice-sync';
 
@@ -215,7 +215,7 @@ export class AddonModChoiceProvider {
             return currentChoice;
         }
 
-        throw new CoreError('Choice not found.');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/data/services/data.ts b/src/addons/mod/data/services/data.ts
index 47665a5ca..5d40d3cd8 100644
--- a/src/addons/mod/data/services/data.ts
+++ b/src/addons/mod/data/services/data.ts
@@ -25,7 +25,7 @@ import { CoreFilepool } from '@services/filepool';
 import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
 import { CoreUtils } from '@services/utils/utils';
 import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
-import { makeSingleton } from '@singletons';
+import { makeSingleton, Translate } from '@singletons';
 import { AddonModDataFieldsDelegate } from './data-fields-delegate';
 import { AddonModDataOffline } from './data-offline';
 import { AddonModDataAutoSyncData, AddonModDataSyncProvider } from './data-sync';
@@ -586,7 +586,7 @@ export class AddonModDataProvider {
             return currentData;
         }
 
-        throw new CoreError('Activity not found');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/feedback/services/feedback.ts b/src/addons/mod/feedback/services/feedback.ts
index c1b696b67..3208cd482 100644
--- a/src/addons/mod/feedback/services/feedback.ts
+++ b/src/addons/mod/feedback/services/feedback.ts
@@ -22,7 +22,7 @@ import { CoreFilepool } from '@services/filepool';
 import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
 import { CoreUtils } from '@services/utils/utils';
 import { CoreWSExternalFile, CoreWSExternalWarning, CoreWSStoredFile } from '@services/ws';
-import { makeSingleton } from '@singletons';
+import { makeSingleton, Translate } from '@singletons';
 import { AddonModFeedbackOffline } from './feedback-offline';
 import { AddonModFeedbackAutoSyncData, AddonModFeedbackSyncProvider } from './feedback-sync';
 
@@ -605,7 +605,7 @@ export class AddonModFeedbackProvider {
             return currentFeedback;
         }
 
-        throw new CoreError('Feedback not found.');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/folder/services/folder.ts b/src/addons/mod/folder/services/folder.ts
index fd73dcd51..f868c2e27 100644
--- a/src/addons/mod/folder/services/folder.ts
+++ b/src/addons/mod/folder/services/folder.ts
@@ -20,7 +20,7 @@ import { CoreCourseLogHelper } from '@features/course/services/log-helper';
 import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites';
 import { CoreUtils } from '@services/utils/utils';
 import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
-import { makeSingleton } from '@singletons';
+import { makeSingleton, Translate } from '@singletons';
 
 const ROOT_CACHE_KEY = 'mmaModFolder:';
 
@@ -80,7 +80,7 @@ export class AddonModFolderProvider {
             return currentFolder;
         }
 
-        throw new CoreError('Folder not found');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/forum/services/forum.ts b/src/addons/mod/forum/services/forum.ts
index bf53d6c30..86da4b29e 100644
--- a/src/addons/mod/forum/services/forum.ts
+++ b/src/addons/mod/forum/services/forum.ts
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 import { Injectable } from '@angular/core';
+import { CoreError } from '@classes/errors/error';
 import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
 import { CoreCourseCommonModWSOptions } from '@features/course/services/course';
 import { CoreCourseLogHelper } from '@features/course/services/log-helper';
@@ -480,7 +481,7 @@ export class AddonModForumProvider {
         const forum = forums.find(forum => forum.cmid == cmId);
 
         if (!forum) {
-            throw new Error('Forum not found');
+            throw new CoreError(Translate.instant('core.course.modulenotfound'));
         }
 
         return forum;
diff --git a/src/addons/mod/glossary/services/glossary.ts b/src/addons/mod/glossary/services/glossary.ts
index e5f6cef2d..a9476adbe 100644
--- a/src/addons/mod/glossary/services/glossary.ts
+++ b/src/addons/mod/glossary/services/glossary.ts
@@ -811,7 +811,7 @@ export class AddonModGlossaryProvider {
             return glossary;
         }
 
-        throw new CoreError('Glossary not found.');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
@@ -835,7 +835,7 @@ export class AddonModGlossaryProvider {
             return glossary;
         }
 
-        throw new CoreError('Glossary not found.');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/h5pactivity/services/h5pactivity.ts b/src/addons/mod/h5pactivity/services/h5pactivity.ts
index 7f16095fc..2c7f3f6d7 100644
--- a/src/addons/mod/h5pactivity/services/h5pactivity.ts
+++ b/src/addons/mod/h5pactivity/services/h5pactivity.ts
@@ -528,7 +528,7 @@ export class AddonModH5PActivityProvider {
             return currentActivity;
         }
 
-        throw new CoreError(Translate.instant('addon.mod_h5pactivity.errorgetactivity'));
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/imscp/components/index/index.ts b/src/addons/mod/imscp/components/index/index.ts
index b6c6e301b..6941f8acc 100644
--- a/src/addons/mod/imscp/components/index/index.ts
+++ b/src/addons/mod/imscp/components/index/index.ts
@@ -14,10 +14,7 @@
 
 import { Component, OnInit, Optional } from '@angular/core';
 import { CoreSilentError } from '@classes/errors/silenterror';
-import {
-    CoreCourseModuleMainResourceComponent,
-    CoreCourseResourceDownloadResult,
-} from '@features/course/classes/main-resource-component';
+import { CoreCourseModuleMainResourceComponent } from '@features/course/classes/main-resource-component';
 import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
 import { CoreCourse } from '@features/course/services/course';
 import { CoreDomUtils } from '@services/utils/dom';
@@ -81,25 +78,13 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom
      * @return Promise resolved when done.
      */
     protected async fetchContent(refresh = false): Promise<void> {
-        let downloadResult: CoreCourseResourceDownloadResult;
-        const promises: Promise<void>[] = [];
+        try {
+            const downloadResult = await this.downloadResourceIfNeeded(refresh);
 
-        promises.push(AddonModImscp.getImscp(this.courseId, this.module.id).then((imscp) => {
+            const imscp = await AddonModImscp.getImscp(this.courseId, this.module.id);
             this.description = imscp.intro;
             this.dataRetrieved.emit(imscp);
 
-            return;
-        }));
-
-        promises.push(this.downloadResourceIfNeeded(refresh).then((result) => {
-            downloadResult = result;
-
-            return;
-        }));
-
-        try {
-            await Promise.all(promises);
-
             this.items = AddonModImscp.createItemList(this.module.contents);
 
             if (this.items.length && typeof this.currentItem == 'undefined') {
diff --git a/src/addons/mod/imscp/services/imscp.ts b/src/addons/mod/imscp/services/imscp.ts
index 2cfa5eb3e..df87b4684 100644
--- a/src/addons/mod/imscp/services/imscp.ts
+++ b/src/addons/mod/imscp/services/imscp.ts
@@ -24,7 +24,7 @@ import { CoreSitesCommonWSOptions, CoreSites } from '@services/sites';
 import { CoreTextUtils } from '@services/utils/text';
 import { CoreUtils } from '@services/utils/utils';
 import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
-import { makeSingleton } from '@singletons';
+import { makeSingleton, Translate } from '@singletons';
 
 const ROOT_CACHE_KEY = 'mmaModImscp:';
 
@@ -183,7 +183,7 @@ export class AddonModImscpProvider {
             return currentImscp;
         }
 
-        throw new CoreError('Imscp not found');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/label/services/label.ts b/src/addons/mod/label/services/label.ts
index ca5488a23..21f673e6b 100644
--- a/src/addons/mod/label/services/label.ts
+++ b/src/addons/mod/label/services/label.ts
@@ -19,7 +19,7 @@ import { CoreFilepool } from '@services/filepool';
 import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites';
 import { CoreUtils } from '@services/utils/utils';
 import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
-import { makeSingleton } from '@singletons';
+import { makeSingleton, Translate } from '@singletons';
 
 const ROOT_CACHE_KEY = 'mmaModLabel:';
 
@@ -77,7 +77,7 @@ export class AddonModLabelProvider {
             return currentLabel;
         }
 
-        throw new CoreError('Label not found');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/lesson/services/lesson.ts b/src/addons/mod/lesson/services/lesson.ts
index fe86bbe71..be4d8c826 100644
--- a/src/addons/mod/lesson/services/lesson.ts
+++ b/src/addons/mod/lesson/services/lesson.ts
@@ -1445,7 +1445,7 @@ export class AddonModLessonProvider {
             return currentLesson;
         }
 
-        throw new CoreError('Lesson not found.');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/lti/services/lti.ts b/src/addons/mod/lti/services/lti.ts
index 44e2d7604..35678bb66 100644
--- a/src/addons/mod/lti/services/lti.ts
+++ b/src/addons/mod/lti/services/lti.ts
@@ -110,7 +110,7 @@ export class AddonModLtiProvider {
             return currentLti;
         }
 
-        throw new CoreError('Activity not found.');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/page/components/index/index.ts b/src/addons/mod/page/components/index/index.ts
index acfedd74b..4dad5b9be 100644
--- a/src/addons/mod/page/components/index/index.ts
+++ b/src/addons/mod/page/components/index/index.ts
@@ -13,9 +13,7 @@
 // limitations under the License.
 
 import { Component, OnInit, Optional } from '@angular/core';
-import {
-    CoreCourseModuleMainResourceComponent,
-} from '@features/course/classes/main-resource-component';
+import { CoreCourseModuleMainResourceComponent } from '@features/course/classes/main-resource-component';
 import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
 import { CoreCourse, CoreCourseWSModule } from '@features/course/services/course';
 import { CoreTextUtils } from '@services/utils/text';
@@ -82,70 +80,57 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp
      * @return Promise resolved when done.
      */
     protected async fetchContent(refresh?: boolean): Promise<void> {
-        // Download the resource if it needs to be downloaded.
         try {
+            // Download the resource if it needs to be downloaded.
             const downloadResult = await this.downloadResourceIfNeeded(refresh);
 
-            const promises: Promise<void>[] = [];
+            const results = await Promise.all([
+                this.loadPageData(),
+                AddonModPageHelper.getPageHtml(this.module.contents, this.module.id),
+            ]);
 
-            let getPagePromise: Promise<CoreCourseWSModule | AddonModPagePage>;
-
-            // Get the module to get the latest title and description. Data should've been updated in download.
-            if (this.canGetPage) {
-                getPagePromise = AddonModPage.getPageData(this.courseId, this.module.id);
-            } else {
-                getPagePromise = CoreCourse.getModule(this.module.id, this.courseId);
-            }
-
-            promises.push(getPagePromise.then((page) => {
-                if (!page) {
-                    return;
-                }
-
-                this.description = 'intro' in page ? page.intro : page.description;
-                this.dataRetrieved.emit(page);
-
-                if (!this.canGetPage) {
-                    return;
-                }
-
-                this.page = page;
-
-                // Check if description and timemodified should be displayed.
-                if ('displayoptions' in this.page) {
-                    const options: Record<string, string | boolean> =
-                        CoreTextUtils.unserialize(this.page.displayoptions) || {};
-
-                    this.displayDescription = typeof options.printintro == 'undefined' ||
-                            CoreUtils.isTrueOrOne(options.printintro);
-                    this.displayTimemodified = typeof options.printlastmodified == 'undefined' ||
-                            CoreUtils.isTrueOrOne(options.printlastmodified);
-                } else {
-                    this.displayDescription = true;
-                    this.displayTimemodified = true;
-                }
-
-                this.timemodified = 'timemodified' in this.page ? this.page.timemodified : undefined;
-
-                return;
-            }).catch(() => {
-                // Ignore errors.
-            }));
-
-            // Get the page HTML.
-            promises.push(AddonModPageHelper.getPageHtml(this.module.contents, this.module.id).then((content) => {
-
-                this.contents = content;
-                this.warning = downloadResult?.failed ? this.getErrorDownloadingSomeFilesMessage(downloadResult.error!) : '';
-
-                return;
-            }));
-
-            await Promise.all(promises);
+            this.contents = results[1];
+            this.warning = downloadResult?.failed ? this.getErrorDownloadingSomeFilesMessage(downloadResult.error!) : '';
         } finally {
-            // Pass false because downloadResourceIfNeeded already invalidates and refresh data if refresh=true.
-            this.fillContextMenu(false);
+            this.fillContextMenu(refresh);
         }
     }
 
+    /**
+     * Load page data from WS.
+     *
+     * @return Promise resolved when done.
+     */
+    protected async loadPageData(): Promise<void> {
+        // Get latest title, description and some extra data. Data should've been updated in download.
+        const page = this.canGetPage ?
+            await AddonModPage.getPageData(this.courseId, this.module.id) :
+            await CoreCourse.getModule(this.module.id, this.courseId);
+
+        this.description = 'intro' in page ? page.intro : page.description;
+        this.dataRetrieved.emit(page);
+
+        if (!this.canGetPage) {
+            return;
+        }
+
+        this.page = page;
+
+        // Check if description and timemodified should be displayed.
+        if ('displayoptions' in this.page) {
+            const options: Record<string, string | boolean> =
+                CoreTextUtils.unserialize(this.page.displayoptions) || {};
+
+            this.displayDescription = typeof options.printintro == 'undefined' ||
+                    CoreUtils.isTrueOrOne(options.printintro);
+            this.displayTimemodified = typeof options.printlastmodified == 'undefined' ||
+                    CoreUtils.isTrueOrOne(options.printlastmodified);
+        } else {
+            this.displayDescription = true;
+            this.displayTimemodified = true;
+        }
+
+        this.timemodified = 'timemodified' in this.page ? this.page.timemodified : undefined;
+    }
+
 }
diff --git a/src/addons/mod/page/services/page.ts b/src/addons/mod/page/services/page.ts
index 42cb139f4..f936f0d64 100644
--- a/src/addons/mod/page/services/page.ts
+++ b/src/addons/mod/page/services/page.ts
@@ -16,7 +16,7 @@ import { Injectable } from '@angular/core';
 import { CoreSitesCommonWSOptions, CoreSites } from '@services/sites';
 import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
 import { CoreWSExternalWarning, CoreWSExternalFile } from '@services/ws';
-import { makeSingleton } from '@singletons';
+import { makeSingleton, Translate } from '@singletons';
 import { CoreFilepool } from '@services/filepool';
 import { CoreCourse } from '@features/course/services/course';
 import { CoreUtils } from '@services/utils/utils';
@@ -79,7 +79,7 @@ export class AddonModPageProvider {
             return currentPage;
         }
 
-        throw new CoreError('Page not found');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/quiz/services/quiz.ts b/src/addons/mod/quiz/services/quiz.ts
index 478a4dce5..30216d969 100644
--- a/src/addons/mod/quiz/services/quiz.ts
+++ b/src/addons/mod/quiz/services/quiz.ts
@@ -748,7 +748,7 @@ export class AddonModQuizProvider {
         const quiz = response.quizzes.find(quiz => quiz[key] == value);
 
         if (!quiz) {
-            throw new CoreError('Quiz not found.');
+            throw new CoreError(Translate.instant('core.course.modulenotfound'));
         }
 
         return quiz;
diff --git a/src/addons/mod/resource/components/index/index.ts b/src/addons/mod/resource/components/index/index.ts
index 11f4241c2..29f8e101e 100644
--- a/src/addons/mod/resource/components/index/index.ts
+++ b/src/addons/mod/resource/components/index/index.ts
@@ -14,9 +14,7 @@
 
 import { Component, OnDestroy, OnInit, Optional } from '@angular/core';
 import { CoreError } from '@classes/errors/error';
-import {
-    CoreCourseModuleMainResourceComponent,
-} from '@features/course/classes/main-resource-component';
+import { CoreCourseModuleMainResourceComponent } from '@features/course/classes/main-resource-component';
 import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
 import { CoreCourse, CoreCourseWSModule } from '@features/course/services/course';
 import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
@@ -118,13 +116,13 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
 
         // Get the resource instance to get the latest name/description and to know if it's embedded.
         if (this.canGetResource) {
-            resource = await CoreUtils.ignoreErrors(AddonModResource.getResourceData(this.courseId, this.module.id));
-            this.description = resource?.intro || '';
-            options = resource?.displayoptions ? CoreTextUtils.unserialize(resource.displayoptions) : {};
+            resource = await AddonModResource.getResourceData(this.courseId, this.module.id);
+            this.description = resource.intro || '';
+            options = resource.displayoptions ? CoreTextUtils.unserialize(resource.displayoptions) : {};
         } else {
-            resource = await CoreUtils.ignoreErrors(CoreCourse.getModule(this.module.id, this.courseId));
-            this.description = resource?.description || '';
-            options = resource?.customdata ? CoreTextUtils.unserialize(CoreTextUtils.parseJSON(resource.customdata)) : {};
+            resource = await CoreCourse.getModule(this.module.id, this.courseId);
+            this.description = resource.description || '';
+            options = resource.customdata ? CoreTextUtils.unserialize(CoreTextUtils.parseJSON(resource.customdata)) : {};
         }
 
         try {
diff --git a/src/addons/mod/resource/services/resource.ts b/src/addons/mod/resource/services/resource.ts
index e99552ac1..23f21dc62 100644
--- a/src/addons/mod/resource/services/resource.ts
+++ b/src/addons/mod/resource/services/resource.ts
@@ -21,7 +21,7 @@ import { CoreFilepool } from '@services/filepool';
 import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites';
 import { CoreUtils } from '@services/utils/utils';
 import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
-import { makeSingleton } from '@singletons';
+import { makeSingleton, Translate } from '@singletons';
 
 const ROOT_CACHE_KEY = 'mmaModResource:';
 
@@ -82,7 +82,7 @@ export class AddonModResourceProvider {
             return currentResource;
         }
 
-        throw new CoreError('Resource not found');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/scorm/services/scorm.ts b/src/addons/mod/scorm/services/scorm.ts
index daeace34c..340eb6ed8 100644
--- a/src/addons/mod/scorm/services/scorm.ts
+++ b/src/addons/mod/scorm/services/scorm.ts
@@ -1105,7 +1105,7 @@ export class AddonModScormProvider {
 
         const currentScorm = <AddonModScormScorm> response.scorms.find(scorm => scorm[key] == value);
         if (!currentScorm) {
-            throw new CoreError('SCORM not found.');
+            throw new CoreError(Translate.instant('core.course.modulenotfound'));
         }
 
         // If the SCORM isn't available the WS returns a warning and it doesn't return timeopen and timeclosed.
diff --git a/src/addons/mod/survey/services/survey.ts b/src/addons/mod/survey/services/survey.ts
index a6d5d9997..523a7fa8d 100644
--- a/src/addons/mod/survey/services/survey.ts
+++ b/src/addons/mod/survey/services/survey.ts
@@ -22,7 +22,7 @@ import { CoreFilepool } from '@services/filepool';
 import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites';
 import { CoreUtils } from '@services/utils/utils';
 import { CoreStatusWithWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
-import { makeSingleton } from '@singletons';
+import { makeSingleton, Translate } from '@singletons';
 import { AddonModSurveyOffline } from './survey-offline';
 
 const ROOT_CACHE_KEY = 'mmaModSurvey:';
@@ -121,7 +121,7 @@ export class AddonModSurveyProvider {
             return currentSurvey;
         }
 
-        throw new CoreError('Activity not found.');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/url/components/index/addon-mod-url-index.html b/src/addons/mod/url/components/index/addon-mod-url-index.html
index d673cbea8..48f9b1f91 100644
--- a/src/addons/mod/url/components/index/addon-mod-url-index.html
+++ b/src/addons/mod/url/components/index/addon-mod-url-index.html
@@ -28,7 +28,7 @@
         <core-iframe [src]="url"></core-iframe>
     </div>
 
-    <ion-list *ngIf="!shouldIframe && (!shouldEmbed || !isOther)">
+    <ion-list *ngIf="url && !shouldIframe && (!shouldEmbed || !isOther)">
         <ion-item *ngIf="shouldEmbed">
             <ion-label>
                 <img *ngIf="isImage" [alt]="name" [src]="url">
diff --git a/src/addons/mod/url/services/url.ts b/src/addons/mod/url/services/url.ts
index 45b260224..2cac565ba 100644
--- a/src/addons/mod/url/services/url.ts
+++ b/src/addons/mod/url/services/url.ts
@@ -16,7 +16,7 @@ import { Injectable } from '@angular/core';
 import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites';
 import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
 import { CoreWSExternalWarning, CoreWSExternalFile } from '@services/ws';
-import { makeSingleton } from '@singletons';
+import { makeSingleton, Translate } from '@singletons';
 import { CoreConstants } from '@/core/constants';
 import { CoreMimetypeUtils } from '@services/utils/mimetype';
 import { CoreCourse } from '@features/course/services/course';
@@ -131,7 +131,7 @@ export class AddonModUrlProvider {
             return currentUrl;
         }
 
-        throw new CoreError('Url not found');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/wiki/services/wiki.ts b/src/addons/mod/wiki/services/wiki.ts
index 5a10fc8b9..f150b3834 100644
--- a/src/addons/mod/wiki/services/wiki.ts
+++ b/src/addons/mod/wiki/services/wiki.ts
@@ -397,7 +397,7 @@ export class AddonModWikiProvider {
             return currentWiki;
         }
 
-        throw new CoreError('Wiki not found.');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**
diff --git a/src/addons/mod/workshop/services/workshop.ts b/src/addons/mod/workshop/services/workshop.ts
index ba637e2ff..27d802240 100644
--- a/src/addons/mod/workshop/services/workshop.ts
+++ b/src/addons/mod/workshop/services/workshop.ts
@@ -23,7 +23,7 @@ import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@
 import { CoreTextFormat, defaultTextFormat } from '@services/utils/text';
 import { CoreUtils } from '@services/utils/utils';
 import { CoreStatusWithWarningsWSResponse, CoreWS, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
-import { makeSingleton } from '@singletons';
+import { makeSingleton, Translate } from '@singletons';
 import { CoreFormFields } from '@singletons/form';
 import { AddonModWorkshopOffline } from './workshop-offline';
 import { AddonModWorkshopAutoSyncData, AddonModWorkshopSyncProvider } from './workshop-sync';
@@ -272,7 +272,7 @@ export class AddonModWorkshopProvider {
 
         const workshop = response.workshops.find((workshop) => workshop[key] == value);
         if (!workshop) {
-            throw new CoreError('Activity not found');
+            throw new CoreError(Translate.instant('core.course.modulenotfound'));
         }
 
         // Set submission types for Moodle 3.5 and older.
diff --git a/src/core/features/course/classes/main-activity-component.ts b/src/core/features/course/classes/main-activity-component.ts
index a601ad17a..fa0d93546 100644
--- a/src/core/features/course/classes/main-activity-component.ts
+++ b/src/core/features/course/classes/main-activity-component.ts
@@ -26,6 +26,7 @@ import { CoreDomUtils } from '@services/utils/dom';
 import { CoreWSExternalWarning } from '@services/ws';
 import { CoreCourseContentsPage } from '../pages/contents/contents';
 import { CoreConstants } from '@/core/constants';
+import { CoreSites } from '@services/sites';
 
 /**
  * Template class to easily create CoreCourseModuleMainComponent of activities.
@@ -211,7 +212,7 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
 
             await this.fetchContent(refresh, sync, showErrors);
         } catch (error) {
-            if (!refresh) {
+            if (!refresh && !CoreSites.getCurrentSite()?.isOfflineDisabled()) {
                 // Some call failed, retry without using cache since it might be a new activity.
                 return await this.refreshContent(sync);
             }
diff --git a/src/core/features/course/lang.json b/src/core/features/course/lang.json
index f383e9d84..7afa1a068 100644
--- a/src/core/features/course/lang.json
+++ b/src/core/features/course/lang.json
@@ -41,6 +41,7 @@
     "insufficientavailablespace": "You are trying to download {{size}}. This will leave your device with insufficient space to operate normally. Please clear some storage space first.",
     "insufficientavailablequota": "Your device could not allocate space to save this download. It may be reserving space for app and system updates. Please clear some storage space first.",
     "manualcompletionnotsynced": "Manual completion not synchronised.",
+    "modulenotfound": "Resource or activity not found, please make sure you're online and it's still available.",
     "nocontentavailable": "No content available at the moment.",
     "overriddennotice": "Your final grade from this activity was manually adjusted.",
     "refreshcourse": "Refresh course",
diff --git a/src/core/features/course/services/course.ts b/src/core/features/course/services/course.ts
index e03b779a2..8aa879d2c 100644
--- a/src/core/features/course/services/course.ts
+++ b/src/core/features/course/services/course.ts
@@ -505,7 +505,7 @@ export class CoreCourseProvider {
             return foundModule;
         }
 
-        throw Error('Module not found');
+        throw new CoreError(Translate.instant('core.course.modulenotfound'));
     }
 
     /**