immich-app/immich · error · Error
Codec ' ' does not support HLS codec strings
Error message
Codec '${codec}' does not support HLS codec strings What it means
getCodecString builds the HLS CODECS attribute string for a target video codec, but only H.264, HEVC, and AV1 have defined codec-string builders. Other codecs (e.g. VP9 or unknown values) cannot be represented in this HLS string, so the default branch throws.
Solutions
- Switch targetVideoCodec to H.264, HEVC, or AV1 for HLS transcoding
- If VP9 output is required, use a non-HLS delivery path (e.g. MP4/WebM progressive)
- Upgrade Immich if a newer version added codec-string support for your codec
Example fix
// before config.targetVideoCodec = VideoCodec.Vp9; const str = getCodecString(config.targetVideoCodec, w, h, fps); // after config.targetVideoCodec = VideoCodec.Hevc; const str = getCodecString(config.targetVideoCodec, w, h, fps);
Defensive patterns
Strategy: validation
Validate before calling
const HLS_CODECS = ['h264', 'hevc', 'av1'];
if (!HLS_CODECS.includes(config.targetVideoCodec)) {
throw new Error(`${config.targetVideoCodec} cannot be used for HLS; pick h264/hevc/av1`);
} Type guard
const supportsHls = (c) => c === 'h264' || c === 'hevc' || c === 'av1';
Try / catch
try {
const s = getCodecString(config.targetVideoCodec, w, h, fps);
} catch (e) {
if (/does not support HLS codec strings/.test(e.message)) {
// fall back to a supported codec or non-HLS delivery
}
} Prevention
- Restrict codec selection UI to HLS-capable codecs when generating HLS
- Keep config enum values synced with the server version
- Test transcode configs in a staging instance
When it happens
Trigger: Transcoding configured with targetVideoCodec set to a codec without an HLS codec-string case (e.g. VideoCodec.Vp9) while generating HLS output.
Common situations: Choosing VP9 as the target codec expecting it to work everywhere; config from experimental versions; enum value drift after codec additions/removals.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Codec ' ' is unsupported
- acceleration does not support codec ' '. Supported codecs
- acceleration is unsupported
- Asset metadata is not yet ready for streaming
- Asset not found or asset is not a video
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/df3c7d1564da3bd4.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/utils/media.ts:64
const pickLevel = (levels: CodecLevel[], frame: number, rate: number) =>
levels.find((level) => frame <= level.maxFrame && rate <= level.maxRate) ?? levels.at(-1)!;
export const getCodecString = (codec: VideoCodec, width: number, height: number, fps: number): string => {
switch (codec) {
case VideoCodec.H264: {
const macroblocks = Math.ceil(width / 16) * Math.ceil(height / 16);
return `avc1.6400${pickLevel(H264_LEVELS, macroblocks, macroblocks * fps).token}`;
}
case VideoCodec.Hevc: {
const samples = width * height;
return `hvc1.1.6.${pickLevel(HEVC_LEVELS, samples, samples * fps).token}.B0`;
}
case VideoCodec.Av1: {
const samples = width * height;
return `av01.0.${pickLevel(AV1_LEVELS, samples, samples * fps).token}.08`;
}
default: {
throw new Error(`Codec '${codec}' does not support HLS codec strings`);
}
}
};
export class BaseConfig implements VideoCodecSWConfig {
readonly presets = ['veryslow', 'slower', 'slow', 'medium', 'fast', 'faster', 'veryfast', 'superfast', 'ultrafast'];
protected constructor(
protected config: ConfigFFmpegDto,
protected tune: VideoTuning = { strictGop: false, lowLatency: false },
) {}
static create(config: ConfigFFmpegDto, interfaces: VideoInterfaces, tune?: VideoTuning) {
if (config.accel === TranscodeHardwareAcceleration.Disabled) {
return BaseConfig.getSWCodecConfig(config, tune);
}
return BaseConfig.getHWCodecConfig(config, interfaces, tune);
}
View on GitHub (pinned to e55ac299a4)