{"record":{"id":"38aad68b85c71214","repo":"withastro/astro","slug":"expectedimageoptions-38aad6","errorCode":"ExpectedImageOptions","errorMessage":"**${collection}** entry is missing an ID.\nInvalid data type: ${typeof data}","messagePattern":"\\*\\*(.+?)\\*\\* entry is missing an ID\\.\nInvalid data type: (.+?)","errorType":"error_code","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/content/content-layer.ts","lineNumber":534,"sourceCode":"\t\treturn;\n\t}\n\tif (typeof data === 'object') {\n\t\tfor (const [id, raw] of Object.entries(data)) {\n\t\t\tif (raw.id && raw.id !== id) {\n\t\t\t\tthrow new AstroError({\n\t\t\t\t\t...AstroErrorData.ContentLoaderInvalidDataError,\n\t\t\t\t\tmessage: AstroErrorData.ContentLoaderInvalidDataError.message(\n\t\t\t\t\t\tcontext.collection,\n\t\t\t\t\t\t`Object key ${JSON.stringify(id)} does not match ID ${JSON.stringify(raw.id)}`,\n\t\t\t\t\t),\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst item = await context.parseData({ id, data: raw });\n\t\t\tcontext.store.set({ id, data: item });\n\t\t}\n\t\treturn;\n\t}\n\tthrow new AstroError({\n\t\t...AstroErrorData.ExpectedImageOptions,\n\t\tmessage: AstroErrorData.ContentLoaderInvalidDataError.message(\n\t\t\tcontext.collection,\n\t\t\t`Invalid data type: ${typeof data}`,\n\t\t),\n\t});\n}\n","sourceCodeStart":516,"sourceCodeEnd":542,"githubUrl":"https://github.com/withastro/astro/blob/d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca/packages/astro/src/content/content-layer.ts#L516-L542","documentation":"Thrown by the content layer's internal simpleLoader when a collection loader returns data that is neither an array nor an object after zod validation. The message reports the invalid typeof. NOTE: the implementation spreads AstroErrorData.ExpectedImageOptions (so the error name/title read 'ExpectedImageOptions' / 'Expected image options.') but constructs the message via ContentLoaderInvalidDataError.message — a mismatch bug; the intended error data is ContentLoaderInvalidDataError. In practice this branch is defensive/unreachable because loaderReturnSchema already restricts data to array|object.","triggerScenarios":"A custom collection loader (CollectionLoader<TData>) passed to the content layer returns a primitive (string, number, boolean) or null/undefined that somehow bypasses loaderReturnSchema, reaching the final fallback throw in simpleLoader().","commonSituations":"Authoring a custom loader whose handler() returns a non-array/non-object value; corrupt or unexpectedly-typed data from an upstream source the loader wraps; future schema changes that widen accepted types without updating the dispatch branches.","solutions":["Ensure your custom loader's handler returns either an array of {id} objects or a Record<string, object> — never a primitive.","If you maintain the loaderReturnSchema, verify it rejects non-array/non-object input so this branch never executes.","File an Astro issue: the thrown error should spread ContentLoaderInvalidDataError, not ExpectedImageOptions (mismatched name/title vs message)."],"exampleFix":"// before - loader returns a primitive\nexport function myLoader(): CollectionLoader<string> {\n  return () => fs.readFileSync('data.txt', 'utf-8');\n}\n// after - return an array of {id} entries\nexport function myLoader(): CollectionLoader<{id: string; content: string}> {\n  return () => [{ id: 'data', content: fs.readFileSync('data.txt', 'utf-8') }];\n}","handlingStrategy":"validation","validationCode":"// In a custom loader, validate the return shape before yielding\nfunction assertLoaderResult(value: unknown): asserts value is Array<{id:string}> | Record<string, any> {\n  if (Array.isArray(value)) {\n    for (const v of value) if (typeof v?.id !== 'string' && typeof v?.id !== 'number') throw new TypeError('entry missing id');\n  } else if (value && typeof value === 'object') {\n    // ok\n  } else {\n    throw new TypeError(`loader must return array or object, got ${typeof value}`);\n  }\n}","typeGuard":"function isLoaderData(v: unknown): v is Array<{id:string}> | Record<string, Record<string, unknown>> {\n  return Array.isArray(v) || (typeof v === 'object' && v !== null);\n}","tryCatchPattern":null,"preventionTips":["Always return an array of {id} objects or a Record from custom loaders.","Unit-test loaders with representative data shapes before wiring them into a collection.","Report the ExpectedImageOptions/ContentLoaderInvalidDataError mismatch upstream so the error name is correct."],"tags":["content-collections","content-layer","loader","bug"],"backgroundTag":null,"analyzedSha":"d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca","analyzedAt":"2026-08-12T13:37:29.035Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}