{"record":{"id":"330b4971a5e67781","repo":"immich-app/immich","slug":"skipped-transcoding-for-asset-asset-id-no-video-dimensions","errorCode":null,"errorMessage":"Skipped transcoding for asset ${asset.id}: no video dimensions","messagePattern":"Skipped transcoding for asset (.+?): no video dimensions","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/src/services/media.service.ts","lineNumber":565,"sourceCode":"  @OnJob({ name: JobName.AssetEncodeVideo, queue: QueueName.VideoConversion })\n  async handleVideoConversion({ id }: JobOf<JobName.AssetEncodeVideo>): Promise<JobStatus> {\n    const asset = await this.assetJobRepository.getForVideoConversion(id);\n    if (!asset) {\n      return JobStatus.Failed;\n    }\n\n    const input = asset.originalPath;\n    const output = StorageCore.getEncodedVideoPath(asset);\n    this.storageCore.ensureFolders(output);\n\n    const { videoStream, format } = asset;\n    const audioStream = asset.audioStream ?? undefined;\n    if (!videoStream || !format) {\n      this.logger.warn(`Skipped transcoding for asset ${asset.id}: missing metadata; re-run extraction first`);\n      return JobStatus.Failed;\n    }\n    if (!videoStream.height || !videoStream.width) {\n      this.logger.warn(`Skipped transcoding for asset ${asset.id}: no video dimensions`);\n      return JobStatus.Failed;\n    }\n\n    let { ffmpeg } = await this.getConfig({ withCache: true });\n    const target = this.getTranscodeTarget(ffmpeg, videoStream, audioStream);\n    if (target === TranscodeTarget.None && !this.isRemuxRequired(ffmpeg, format)) {\n      const encodedVideo = getAssetFile(asset.files, AssetFileType.EncodedVideo, { isEdited: false });\n      if (encodedVideo) {\n        this.logger.log(`Transcoded video exists for asset ${asset.id}, but is no longer required. Deleting...`);\n        await this.jobRepository.queue({ name: JobName.FileDelete, data: { files: [encodedVideo.path] } });\n        await this.assetRepository.deleteFiles([encodedVideo]);\n      } else {\n        this.logger.verbose(`Asset ${asset.id} does not require transcoding based on current policy, skipping`);\n      }\n\n      return JobStatus.Skipped;\n    }\n","sourceCodeStart":547,"sourceCodeEnd":583,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/media.service.ts#L547-L583","documentation":"After confirming stream/format metadata exist, transcoding still requires nonzero video dimensions (height and width) to compute scaling and target bitrate. A video stream without dimensions is logged with this warning and the job returns JobStatus.Failed.","triggerScenarios":"handleVideoConversion reads a videoStream row where height or width is 0/null — typically from a partial or failed ffprobe extraction, or a codec ffprobe could not measure (e.g. exotic codecs, rotated streams with missing side data).","commonSituations":"ffprobe version issues producing empty dimension fields; corrupted or truncated video files; unusual codecs (e.g. some AV1/ProRes variants) on older ffmpeg builds; rows written before dimensions were extracted.","solutions":["Re-run metadata extraction for the asset to repopulate height/width","Verify the file with ffprobe/ffmpeg -i; replace or re-upload if the video is corrupt","Upgrade ffmpeg/ffprobe if the codec's dimensions cannot be probed","Check DB: SELECT width, height FROM video_stream WHERE asset_id = '<id>' to confirm the bad row"],"exampleFix":"// before\nif (!videoStream.height || !videoStream.width) { this.logger.warn(`Skipped transcoding for asset ${asset.id}: no video dimensions`); return JobStatus.Failed; }\n// after\nif (!videoStream.height || !videoStream.width) { this.logger.warn(`Skipped transcoding for asset ${asset.id}: no video dimensions`); await this.jobRepository.queue({ name: JobName.VideoMetadata, data: { id: asset.id } }); return JobStatus.Failed; }","handlingStrategy":"retry","validationCode":"if (videoStream && (!videoStream.height || !videoStream.width)) {\n  await jobRepository.queue({ name: JobName.VideoMetadata, data: { id: asset.id } }); // re-extract dimensions\n}","typeGuard":null,"tryCatchPattern":"if (!videoStream.height || !videoStream.width) {\n  this.logger.warn(`Skipped transcoding for asset ${asset.id}: no video dimensions`);\n  return JobStatus.Failed; // then re-run metadata extraction and retry\n}","preventionTips":["Re-run metadata extraction for assets with 0/null dimensions","Test problem files with ffprobe to confirm dimensions are extractable","Keep ffmpeg/ffprobe current for new codecs","Reject or quarantine uploads whose probe yields no dimensions"],"tags":["video","transcoding","metadata"],"backgroundTag":"value-out-of-range","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}