nextcloud/server · error · OCSNotFoundException

Media file not found

Error message

Media file not found

What it means

OCSNotFoundException (HTTP 404) thrown by DiscoverController::mediaImage when fetching or storing the remote media file fails: the HTTP client get($fileName) throws (unreachable host, 404, timeout) or storing into the appdata folder via newFile fails (disk full, no appdata). The catch wraps any Throwable into this single 'Media file not found' response and logs a warning with the media_src.

Source

Thrown at apps/appstore/lib/Controller/DiscoverController.php:138

				24,
				60 * 60,
				$user,
			);

			if (!$this->checkCanDownloadMedia($fileName)) {
				$this->logger->warning('Tried to load media files for app discover section from untrusted source');
				throw new OCSBadRequestException('Untrusted media source');
			}

			try {
				$client = $this->clientService->newClient();
				$fileResponse = $client->get($fileName);
				$contentType = $fileResponse->getHeader('Content-Type');
				$extension = $info['extension'] ?? '';
				$file = $folder->newFile($hashName . '.' . base64_encode($contentType) . '.' . $extension, $fileResponse->getBody());
			} catch (\Throwable $e) {
				$this->logger->warning('Could not load media file for app discover section', ['media_src' => $fileName, 'exception' => $e]);
				throw new OCSNotFoundException('Media file not found');
			}
		} else {
			// File was found so we can get the content type from the file name
			$contentType = base64_decode(explode('.', $file->getName())[1] ?? '');
		}

		$response = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => $contentType]);
		// cache for 7 days
		$response->cacheFor(604800, false, true);
		return $response;
	}

	private function checkCanDownloadMedia(string $filename): bool {
		$urlInfo = parse_url($filename);
		if (!isset($urlInfo['host']) || !isset($urlInfo['path'])) {
			return false;
		}

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Retry later if the app store endpoint was transiently unavailable (the response is cached, so a later successful fetch repairs it)
  2. From the server host, verify the failing media_src URL is reachable (curl) — if egress is blocked, allow it
  3. Check the warning log entry 'Could not load media file for app discover section' for the exact media_src and exception
  4. If appdata is broken, ensure the folder exists and is writable; a successful refetch will repopulate it
Defensive patterns

Strategy: retry

Try / catch

async function fetchDiscoverMedia(url: string, attempts = 3) {
	for (let i = 0; i < attempts; i++) {
		try {
			return await axios.get(url)
		} catch (e) {
			if (i === attempts - 1) {
				// 404 'Media file not found' — log and fall back to a placeholder image
				return PLACEHOLDER
			}
			await new Promise((r) => setTimeout(r, 2 ** i * 500)) // backoff before retry
		}
	}
}

Prevention

When it happens

Trigger: Discover section requesting a screenshot whose remote URL is dead (removed from CDN), the app store host unreachable from the server (firewall/egress rules), DNS failure, or the appdata folder for discover media missing/not writable.

Common situations: App store CDN hiccups; servers with restricted outbound traffic; cached app metadata referencing screenshots that the publisher deleted; appdata on a full/read-only volume.

Related errors


AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17). Data as JSON: /api/errors/dd06aadc858f12a2. Report an issue: GitHub.