immich-app/immich · error · StateError

Failed to load animated codec for local asset

Error message

Failed to load animated codec for local asset ${key.id}

What it means

local_image_provider's animated variant loads a codec for a local asset; when loadCodecRequest returns null (no decodable animated frame could be produced for the asset id), a StateError is thrown because an animated codec is required to emit.

Solutions

  1. Fall back to the static (non-animated) decode path when the animated codec is null
  2. Pre-check the asset's mime/format and route unsupported animated formats to the static provider
  3. Skip or placeholder the asset instead of throwing when it is unreadable

Example fix

// before
final codec = await loadCodecRequest(originalRequest, isFinal: true);
if (codec == null) throw StateError('Failed to load animated codec ...');
// after
final codec = await loadCodecRequest(originalRequest, isFinal: true) ??
    await loadStaticCodec(originalRequest); // graceful fallback
Defensive patterns

Strategy: fallback

Validate before calling

// Dart: confirm the asset is still present and decodable
final exists = await fileExistsForAsset(key.id);
if (!exists) return placeholderCodec();

Try / catch

try {
  yield* animatedFrames(key);
} on StateError catch (e) {
  log('animated decode failed: $e');
  yield* staticFrames(key); // non-animated fallback
}

Prevention

When it happens

Trigger: ImageStreamDecorator-style request for a local asset whose animated codec cannot be loaded: unsupported/unknown animated format, asset file unreadable, or decoder returned no frames for key.id.

Common situations: Displaying a corrupted or exotic animated asset (rare GIF/HEVC variants); asset deleted or moved after it was picked; plugin/decoder limitation on specific formats.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at mobile/lib/presentation/widgets/images/local_image_provider.dart:193

    final previewRequest = request = LocalImageRequest(
      localId: key.id,
      size: _previewTarget(devicePixelRatio, false),
      assetType: key.assetType,
    );
    yield* loadRequest(previewRequest, decode, isFinal: false);

    if (isCancelled) {
      return;
    }

    // always try original for animated, since previews don't support animation
    final originalRequest = request = LocalImageRequest(localId: key.id, size: Size.zero, assetType: key.assetType);
    final codec = await loadCodecRequest(originalRequest, isFinal: true);
    if (codec == null) {
      if (isCancelled) {
        return;
      }
      throw StateError('Failed to load animated codec for local asset ${key.id}');
    }
    yield codec;
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (other is LocalFullImageProvider) {
      return id == other.id &&
          size == other.size &&
          isAnimated == other.isAnimated &&
          width == other.width &&
          height == other.height &&
          checksum == other.checksum;
    }
    return false;

View on GitHub (pinned to e55ac299a4)