immich-app/immich · warning · NotFoundException

Asset metadata is not yet ready for streaming

Error message

Asset metadata is not yet ready for streaming

What it means

After realtime transcoding is confirmed enabled, the service looks up precomputed video-stream metadata via videoStreamRepository.getForMainPlaylist. If the asset has no ready HLS/video-stream metadata yet (transcoding analysis not finished), a 404 NotFoundException is returned so the client can retry later.

Solutions

  1. Wait and retry: the video stream worker will populate metadata; the client should retry the playlist request after a delay.
  2. Ensure the microservices (workers) container is running and processing jobs (check job queue for video-stream/transcode jobs).
  3. Verify the asset completed processing (check its status in the web UI) before attempting HLS playback.

Example fix

// before
const playlist = await api.getMainPlaylist(assetId);
// after
const playlist = await withRetry(() => api.getMainPlaylist(assetId), { retries: 5, delayMs: 2000 });
Defensive patterns

Strategy: retry

Validate before calling

const streams = await api.getVideoInfo(assetId);
if (!streams?.videoStreams?.length) console.warn('Video metadata not ready yet; defer HLS request');

Try / catch

try {
  return await api.getMainPlaylist(assetId);
} catch (e) {
  if (e.status === 404 && /not yet ready for streaming/.test(e.message)) {
    await sleep(3000);
    return api.getMainPlaylist(assetId);
  }
  throw e;
}

Prevention

When it happens

Trigger: Requesting the main playlist immediately after upload or after enabling realtime transcoding, before the microservices worker has generated and stored stream metadata for the asset.

Common situations: Scrolling a timeline and hitting play on freshly uploaded videos; first playback after enabling realtime on a large library; worker backlog delaying metadata generation.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15). Data as JSON: /api/errors/75d53b95babe924f. Report an issue: GitHub.

Appendix: source

Thrown at server/src/services/hls.service.ts:56

    this.sessions.delete(sessionId);
    this.pendingSegments.rejectByPrefix(`${sessionId}:`, 'Session ended');
  }

  @OnEvent({ name: 'HlsSegmentResult', server: true, workers: [ImmichWorker.Api] })
  onSegmentResult(event: ArgOf<'HlsSegmentResult'>) {
    this.pendingSegments.complete(this.getSegmentKey(event), event);
  }

  async getMainPlaylist(auth: AuthDto, assetId: string) {
    await this.requireAccess({ auth, permission: Permission.AssetView, ids: [assetId] });
    const { ffmpeg } = await this.getConfig({ withCache: true });
    if (!ffmpeg.realtime.enabled) {
      throw new BadRequestException('Real-time transcoding is not enabled');
    }

    const asset = await this.videoStreamRepository.getForMainPlaylist(assetId);
    if (!asset) {
      throw new NotFoundException('Asset metadata is not yet ready for streaming');
    }

    // Sharing the sessionId allows only one microservices worker to successfully insert to the session table.
    // The microservices worker that creates a session owns the transcoding lifecycle for it.
    const sessionId = this.cryptoRepository.randomUUID();
    this.websocketRepository.serverSend('HlsSessionRequest', { sessionId, assetId, ownerId: auth.user.id });
    await this.pendingSessions.wait(sessionId);
    this.trackSession(sessionId);

    return this.generateMainPlaylist(sessionId, ffmpeg, asset);
  }

  async getMediaPlaylist(auth: AuthDto, assetId: string, sessionId: string, variantIndex: number, position?: number) {
    await this.requireAccess({ auth, permission: Permission.AssetView, ids: [assetId] });

    const asset = await this.videoStreamRepository.getForMediaPlaylist(assetId, sessionId);
    if (!asset) {
      throw new NotFoundException('Asset not found or metadata not yet ready for streaming');

View on GitHub (pinned to e55ac299a4)