{"record":{"id":"7a66a09bc4179c40","repo":"angular/angular","slug":"2952","errorCode":"2952","errorMessage":"${imgDirectiveDetails(dir.ngSrc)} the aspect ratio of the image does not match the aspect ratio indicated by the width and height attributes. \nIntrinsic image size: ${intrinsicWidth}w x ${intrinsicHeight}h (aspect-ratio: ${round(intrinsicAspectRatio)}). \nSupplied width and height attributes: ${suppliedWidth}w x ${suppliedHeight}h (aspect-ratio: ${round(suppliedAspectRatio)}). \nTo fix this, update the width and height attributes.","messagePattern":"(.+?) the aspect ratio of the image does not match the aspect ratio indicated by the width and height attributes\\. \nIntrinsic image size: (.+?)w x (.+?)h \\(aspect-ratio: (.+?)\\)\\. \nSupplied width and height attributes: (.+?)w x (.+?)h \\(aspect-ratio: (.+?)\\)\\. \nTo fix this, update the width and height attributes\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/common/src/directives/ng_optimized_image/ng_optimized_image.ts","lineNumber":1126,"sourceCode":"    const intrinsicAspectRatio = intrinsicWidth / intrinsicHeight;\n\n    const suppliedWidth = dir.width!;\n    const suppliedHeight = dir.height!;\n    const suppliedAspectRatio = suppliedWidth / suppliedHeight;\n\n    // Tolerance is used to account for the impact of subpixel rendering.\n    // Due to subpixel rendering, the rendered, intrinsic, and supplied\n    // aspect ratios of a correctly configured image may not exactly match.\n    // For example, a `width=4030 height=3020` image might have a rendered\n    // size of \"1062w, 796.48h\". (An aspect ratio of 1.334... vs. 1.333...)\n    const inaccurateDimensions =\n      Math.abs(suppliedAspectRatio - intrinsicAspectRatio) > ASPECT_RATIO_TOLERANCE;\n    const stylingDistortion =\n      nonZeroRenderedDimensions &&\n      Math.abs(intrinsicAspectRatio - renderedAspectRatio) > ASPECT_RATIO_TOLERANCE;\n\n    if (inaccurateDimensions) {\n      console.warn(\n        formatRuntimeError(\n          RuntimeErrorCode.INVALID_INPUT,\n          `${imgDirectiveDetails(dir.ngSrc)} the aspect ratio of the image does not match ` +\n            `the aspect ratio indicated by the width and height attributes. ` +\n            `\\nIntrinsic image size: ${intrinsicWidth}w x ${intrinsicHeight}h ` +\n            `(aspect-ratio: ${round(\n              intrinsicAspectRatio,\n            )}). \\nSupplied width and height attributes: ` +\n            `${suppliedWidth}w x ${suppliedHeight}h (aspect-ratio: ${round(\n              suppliedAspectRatio,\n            )}). ` +\n            `\\nTo fix this, update the width and height attributes.`,\n        ),\n      );\n    } else if (stylingDistortion) {\n      console.warn(\n        formatRuntimeError(\n          RuntimeErrorCode.INVALID_INPUT,","sourceCodeStart":1108,"sourceCodeEnd":1144,"githubUrl":"https://github.com/angular/angular/blob/51cb07e98081ab7e4e84a9e0949266a8e19cca84/packages/common/src/directives/ng_optimized_image/ng_optimized_image.ts#L1108-L1144","documentation":"After an NgOptimizedImage loads, dev-mode validators compare the aspect ratio implied by the width/height attributes against the image file's intrinsic ratio (naturalWidth/naturalHeight). If they diverge by more than ASPECT_RATIO_TOLERANCE (0.1), warning NG02952 (INVALID_INPUT) fires with both ratios printed and asks you to correct the attributes. Wrong attribute ratios reserve the wrong layout box and cause layout shift (CLS) before the image loads.","triggerScenarios":"`<img ngSrc=\"photo.jpg\" width=\"400\" height=\"400\">` where photo.jpg is intrinsically 800x600; the check runs in dev mode once the image has loaded and natural dimensions are known.","commonSituations":"Hard-coded width/height copied from design mockups while the asset changed; CMS images whose ratio varies per item; swapping image assets without updating templates.","solutions":["Update the width/height attributes so their ratio matches the intrinsic image (e.g., 800x600 asset -> width=\"800\" height=\"600\" or width=\"400\" height=\"300\")","If the display box must differ from the file's ratio, fix the asset (crop it) so the attributes tell the truth","Generate the attributes from image metadata in the build (e.g., a CI step comparing template dimensions against files)"],"exampleFix":"<!-- before: file is 800x600 (4:3), attributes claim 1:1 -->\n<img ngSrc=\"photo.jpg\" width=\"400\" height=\"400\" />\n\n<!-- after -->\n<img ngSrc=\"photo.jpg\" width=\"400\" height=\"300\" />","handlingStrategy":"validation","validationCode":"function matchesIntrinsicRatio(\n  w: number, h: number, naturalW: number, naturalH: number, tol = 0.1,\n) {\n  return Math.abs(w / h - naturalW / naturalH) <= tol;\n}\n// CI check: compare template attributes against the actual asset\nif (!matchesIntrinsicRatio(400, 400, 800, 600)) {\n  throw new Error('width/height attributes do not match the asset ratio');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive width/height attributes from real asset metadata, not from mockups","Add a CI check comparing template dimensions against the referenced image files","Standardize per-slot image ratios so attributes stay stable"],"tags":["ngoptimizedimage","aspect-ratio","layout-shift","cls","dev-mode"],"backgroundTag":"image-aspect-ratio-mismatch","analyzedSha":"51cb07e98081ab7e4e84a9e0949266a8e19cca84","analyzedAt":"2026-08-22T07:04:54.531Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}