withastro/astro · error · AstroError
ExpectedImageOptions
ExpectedImageOptions
Error message
**${collection}** entry is missing an ID.
Invalid data type: ${typeof data} What it means
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.
Source
Thrown at packages/astro/src/content/content-layer.ts:534
return;
}
if (typeof data === 'object') {
for (const [id, raw] of Object.entries(data)) {
if (raw.id && raw.id !== id) {
throw new AstroError({
...AstroErrorData.ContentLoaderInvalidDataError,
message: AstroErrorData.ContentLoaderInvalidDataError.message(
context.collection,
`Object key ${JSON.stringify(id)} does not match ID ${JSON.stringify(raw.id)}`,
),
});
}
const item = await context.parseData({ id, data: raw });
context.store.set({ id, data: item });
}
return;
}
throw new AstroError({
...AstroErrorData.ExpectedImageOptions,
message: AstroErrorData.ContentLoaderInvalidDataError.message(
context.collection,
`Invalid data type: ${typeof data}`,
),
});
}
View on GitHub (pinned to d081033d5f)
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).
Example fix
// before - loader returns a primitive
export function myLoader(): CollectionLoader<string> {
return () => fs.readFileSync('data.txt', 'utf-8');
}
// after - return an array of {id} entries
export function myLoader(): CollectionLoader<{id: string; content: string}> {
return () => [{ id: 'data', content: fs.readFileSync('data.txt', 'utf-8') }];
} Defensive patterns
Strategy: validation
Validate before calling
// In a custom loader, validate the return shape before yielding
function assertLoaderResult(value: unknown): asserts value is Array<{id:string}> | Record<string, any> {
if (Array.isArray(value)) {
for (const v of value) if (typeof v?.id !== 'string' && typeof v?.id !== 'number') throw new TypeError('entry missing id');
} else if (value && typeof value === 'object') {
// ok
} else {
throw new TypeError(`loader must return array or object, got ${typeof value}`);
}
} Type guard
function isLoaderData(v: unknown): v is Array<{id:string}> | Record<string, Record<string, unknown>> {
return Array.isArray(v) || (typeof v === 'object' && v !== null);
} Prevention
- 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.
When it happens
Trigger: 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().
Common situations: 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.
Related errors
- Live content collections must be defined in "src/live.config
- Collection loader for ${name} does not have a load method
- ContentLoaderReturnsInvalidId
- ContentLoaderInvalidDataError
- FileGlobNotSupported
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/38aad68b85c71214.
Report an issue: GitHub.