{"record":{"id":"97cdd57de43ebe6b","repo":"withastro/astro","slug":"expectedimage-97cdd5","errorCode":"ExpectedImage","errorMessage":"Expected `src` property for `getImage` or `<Image />` to be either an ESM imported image or a string with the path of a remote image. Received `${src}` (type: `${typeofOptions}`).\n\nFull serialized options received: `${fullOptions}`.","messagePattern":"Expected `src` property for `getImage` or `<Image />` to be either an ESM imported image or a string with the path of a remote image\\. Received `(.+?)` \\(type: `(.+?)`\\)\\.\n\nFull serialized options received: `(.+?)`\\.","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/assets/services/service.ts","lineNumber":159,"sourceCode":"}\n\nexport type BaseServiceTransform = {\n\tsrc: string;\n\twidth?: number;\n\theight?: number;\n\tformat?: string;\n\tquality?: string | null;\n\tfit?: ImageFit;\n\tposition?: string;\n\tbackground?: string;\n};\n\nconst sortNumeric = (a: number, b: number) => a - b;\n\nexport function verifyOptions(options: ImageTransform): void {\n\t// `src` is missing or is `undefined`.\n\tif (!options.src || (!isRemoteImage(options.src) && !isESMImportedImage(options.src))) {\n\t\tthrow new AstroError({\n\t\t\t...AstroErrorData.ExpectedImage,\n\t\t\tmessage: AstroErrorData.ExpectedImage.message(\n\t\t\t\tJSON.stringify(options.src),\n\t\t\t\ttypeof options.src,\n\t\t\t\tJSON.stringify(options, (_, v) => (v === undefined ? null : v)),\n\t\t\t),\n\t\t});\n\t}\n\n\tif (!isESMImportedImage(options.src)) {\n\t\t// User passed an `/@fs/` path or a filesystem path instead of the full image.\n\t\tif (\n\t\t\toptions.src.startsWith('/@fs/') ||\n\t\t\t(!isRemotePath(options.src) && !options.src.startsWith('/'))\n\t\t) {\n\t\t\tthrow new AstroError({\n\t\t\t\t...AstroErrorData.LocalImageUsedWrongly,\n\t\t\t\tmessage: AstroErrorData.LocalImageUsedWrongly.message(options.src),","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/withastro/astro/blob/e294953aa8aadd98d5be92e60a03037b05dbdfd4/packages/astro/src/assets/services/service.ts#L141-L177","documentation":"`verifyOptions()` runs inside the base image service for every `<Image>`/`<Picture>`/`getImage()` transform (packages/astro/src/assets/services/service.ts:148). The first check rejects a `src` that is falsy or neither an ESM-imported image (ImageMetadata) nor a remote URL string, throwing `ExpectedImage` with `typeof src` and the full serialized options in the message.","triggerScenarios":"`src` is a number, boolean, plain object, empty string, or null — e.g. `src={123}`, `src={ someObj.src }` where the property does not exist, or a CMS field rendered without a fallback.","commonSituations":"Untyped CMS payloads where the image field is occasionally absent/typed differently; passing `src={image.id}` instead of `src={image.url}`; templating that yields `src=\"[object Object]\"`-like values.","solutions":["Pass either an ESM-imported image object or a full remote URL string (starting with a protocol) as `src`.","Guard dynamic data before render: `if (typeof src !== 'string' && !isESMImport) return null`.","Type your components' props (`src: ImageMetadata | string`) so mismatches surface at compile time."],"exampleFix":"// before — CMS id, not a URL\n<Image src={product.imageAssetId} alt={product.name} />\n\n// after — resolve to the actual URL first\n<Image src={`https://cdn.example.com/assets/${product.imageAssetId}`} alt={product.name} width={800} height={600} />","handlingStrategy":"type-guard","validationCode":"const validSrc =\n  (typeof src === 'string' && /^https?:\\/\\//.test(src)) || isImageMetadata(src);\nif (!validSrc) throw new Error(`Invalid src for <Image>: ${JSON.stringify(src)}`);","typeGuard":"import type { ImageMetadata } from 'astro';\n\nfunction isUsableImageSrc(value: unknown): value is string | ImageMetadata {\n  if (typeof value === 'string') return value.length > 0;\n  return (\n    typeof value === 'object' && value !== null &&\n    'src' in value && 'width' in value && 'height' in value\n  );\n}","tryCatchPattern":null,"preventionTips":["Type the boundary where CMS data enters components and validate image fields there.","Reject records without a usable image early instead of letting components receive junk."],"tags":["images","image-component","validation"],"backgroundTag":"missing-required-argument","analyzedSha":"e294953aa8aadd98d5be92e60a03037b05dbdfd4","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}