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

Before serving a video's main HLS playlist, Immich fetches the asset's prepared video metadata (codec, streams, packets) via videoStreamRepository.getForMainPlaylist. If that returns null - typically because metadata extraction / video probe has not completed for a freshly uploaded asset - it throws 404 NotFoundException. The asset exists and is accessible, but the data needed to plan transcoding variants is not ready yet.

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 199723261c)

Solutions

  1. Wait a few seconds and retry - the playlist becomes available once the metadata/probe job completes.
  2. Check the Jobs dashboard for a stuck or failed MetadataExtraction / video probe queue and re-run it for the asset.
  3. Confirm the microservices container/worker is running (without it the job never processes).
  4. If persistent, trigger metadata re-extraction for the asset from the admin maintenance menu.
Defensive patterns

Strategy: retry

Validate before calling

// check asset is ready before opening the player
const asset = await api.assetApi.get(assetId);
if (!asset?.encodedVideoPath && asset?.type === 'VIDEO') {
  // metadata may still be processing - wait or show a 'preparing' state
  await waitForJob('MetadataExtraction', assetId);
}

Type guard

const isAssetReadyForStreaming = (a: { encodedVideoPath?: string; type: string }) =>
  a.type === 'VIDEO' && !!a.encodedVideoPath;

Try / catch

for (let attempt = 0; attempt < 5; attempt++) {
  try {
    return await api.hlsApi.getMainPlaylist(auth, assetId);
  } catch (e) {
    if (e.status === 404 && /not yet ready/.test(e.message)) {
      await delay(2000 * (attempt + 1));
      continue;
    }
    throw e;
  }
}
throw new Error('Asset metadata never became ready');

Prevention

When it happens

Trigger: User opens a just-uploaded video in the viewer before the MetadataExtraction / video probe job has finished writing the stream info getForMainPlaylist needs. Asset row exists, but its videoStream/segments data is absent.

Common situations: Background jobs backlog; microservices worker not running or crashed; very large video still being probed; metadata job failed silently for that asset.

Related errors


AI-assisted analysis of immich-app/immich@199723261c (2026-08-12). Data as JSON: /api/errors/75d53b95babe924f. Report an issue: GitHub.