{"record":{"id":"de8dada9e6ad4427","repo":"withastro/astro","slug":"imagemissingalt-de8dad","errorCode":"ImageMissingAlt","errorMessage":"Image missing \"alt\" property. \"alt\" text is required to describe important images on the page.","messagePattern":"Image missing \"alt\" property\\. \"alt\" text is required to describe important images on the page\\.","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/components/Picture.astro","lineNumber":38,"sourceCode":"\tformats?: ImageOutputFormat[];\n\tfallbackFormat?: ImageOutputFormat;\n\tpictureAttributes?: HTMLAttributes<'picture'>;\n};\n\nconst defaultFormats = ['webp'] as const;\nconst defaultFallbackFormat = 'png' as const;\n\n// Certain formats don't want PNG fallbacks:\n// - GIF will typically want to stay as a gif, either for animation or for the lower amount of colors\n// - SVGs can't be converted to raster formats in most cases\n// - JPEGs compress photographs and high-noise images better than PNG in most cases\n// For those, we'll use the original format as the fallback instead.\nconst specialFormatsFallback = ['gif', 'svg', 'jpg', 'jpeg'] as const;\n\nconst { formats = defaultFormats, pictureAttributes = {}, fallbackFormat, ...props } = Astro.props;\n\nif (props.alt === undefined || props.alt === null) {\n\tthrow new AstroError(AstroErrorData.ImageMissingAlt);\n}\n\n// Picture attribute inherit scoped styles from class and attributes\nconst scopedStyleClass = props.class?.match(/\\bastro-\\w{8}\\b/)?.[0];\nif (scopedStyleClass) {\n\tif (pictureAttributes.class) {\n\t\tpictureAttributes.class = `${pictureAttributes.class} ${scopedStyleClass}`;\n\t} else {\n\t\tpictureAttributes.class = scopedStyleClass;\n\t}\n}\n\nconst layout = props.layout ?? imageConfig.layout ?? 'none';\nconst useResponsive = layout !== 'none';\n\nif (useResponsive) {\n\tprops.layout ??= imageConfig.layout;\n\tprops.fit ??= imageConfig.objectFit ?? 'cover';","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/astro/components/Picture.astro#L20-L56","documentation":"The built-in `<Picture />` component enforces the same accessibility rule as `<Image />`: `alt` is required and `ImageMissingAlt` is thrown when it is `undefined`/`null`. Note the check inspects the component props, not `pictureAttributes` — putting alt on the wrapping `<picture>` element does not satisfy it.","triggerScenarios":"Rendering `<Picture src={...} formats={[...]} />` without alt; passing `alt` inside `pictureAttributes={{ alt: '...' }}` (which targets the `<picture>` wrapper) instead of as a top-level prop; destructured props where alt was not forwarded.","commonSituations":"Migrating from `<Image>` to `<Picture>` and misplacing attributes; data-driven components that spread `pictureAttributes` and forget the top-level alt; same CMS-missing-alt cases as `<Image>`.","solutions":["Pass alt as a top-level prop: `<Picture src={hero} formats={['avif','webp']} alt=\"Portrait of the founder\" />`","Use `alt=\"\"` explicitly for decorative images","Check that wrapper-level attributes go in `pictureAttributes` but alt goes on the component itself"],"exampleFix":"// before\n<Picture src={hero} formats={['avif', 'webp']} pictureAttributes={{ alt: 'Hero' }} />\n\n// after\n<Picture src={hero} formats={['avif', 'webp']} alt=\"Hero\" pictureAttributes={{ loading: 'eager' }} />","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function hasAlt(props: { alt?: string | null }): boolean {\n  return props.alt != null;\n}","tryCatchPattern":null,"preventionTips":["Put alt on the component, never inside pictureAttributes","Type your data layer so image props are required at the source","Use the same alt discipline for <Picture> as for <Image> — the check is identical"],"tags":["picture","image","accessibility","alt-text","component"],"backgroundTag":"missing-alt-attribute","analyzedSha":"52e6c34790cc8ac4e69e6135ace06049867e5c4a","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}