immich-app/immich · warning · NotFoundException

Asset not found or metadata not yet ready for streaming

Error message

Asset not found or metadata not yet ready for streaming

What it means

When a client requests a media (variant) playlist via getMediaPlaylist, the service calls videoStreamRepository.getForMediaPlaylist(assetId, sessionId). A null result means either the asset was deleted, the asset has not yet had its streaming metadata prepared, or the provided sessionId does not match a known session for the asset. Because all three collapse into null, Immich throws 404 with a combined message.

Source

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

      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');
    }

    const segmentation = this.getSegmentation(asset);
    const hintedSegment = position === undefined ? undefined : this.positionToSegmentIndex(segmentation, position);
    this.prewarmVariant(assetId, sessionId, variantIndex, hintedSegment);

    return this.generateMediaPlaylist(asset, segmentation);
  }

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

View on GitHub (pinned to 199723261c)

Solutions

  1. Re-fetch the main playlist to obtain a fresh sessionId, then request the media playlist again.
  2. If the asset was just uploaded, wait for metadata/segment jobs to finish then retry.
  3. Confirm the asset still exists (GET /assets/{id}); if 404, stop playback.
  4. Ensure microservices are running so session/variant metadata gets produced promptly.
Defensive patterns

Strategy: retry

Validate before calling

// always derive sessionId from a fresh main playlist call
const main = await api.hlsApi.getMainPlaylist(auth, assetId);
const sessionId = parseSessionId(main); // valid before requesting media playlist
await api.hlsApi.getMediaPlaylist(auth, assetId, sessionId, variantIndex);

Type guard

const isValidSession = (s: string | undefined): s is string =>
  typeof s === 'string' && s.length > 0;

Try / catch

try {
  await api.hlsApi.getMediaPlaylist(auth, assetId, sessionId, variantIndex);
} catch (e) {
  if (e.status === 404) {
    // refresh main playlist and retry once with a new session
    const main = await api.hlsApi.getMainPlaylist(auth, assetId);
    return api.hlsApi.getMediaPlaylist(auth, assetId, parseSessionId(main), variantIndex);
  }
  throw e;
}

Prevention

When it happens

Trigger: GET /assets/{id}/video/playlists/media.m3u8?sessionId=...&variantIndex=... where the asset is gone, its media-playlist data isn't ready, or the sessionId is stale/wrong. Common right after the main playlist was generated but before the worker produced variant metadata, or when a stale player retries after session expiry.

Common situations: Player holding a sessionId after the HLS session was closed; race during initial segment generation; asset deleted while someone was watching; microservices lag.

Related errors


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