withastro/astro · error · Error
Collection loader for
Error message
Collection loader for ${name} does not have a load method What it means
During content-layer sync (build or dev), each collection's loader must be either a function (treated as a simple loader) or an object with a `load()` method. This Error is thrown from ContentLayer.sync when a collection's `loader` object has no `load` function — typically a live or malformed loader that reached the sync stage without going through defineCollection's config-time validation.
Solutions
- Implement `load(context)` on the loader object — the build-time loader contract
- If the loader is actually a live loader (loadEntry/loadCollection), move that collection to `src/live.config.ts` with `defineLiveCollection`
- If the loader is a plain function, pass it directly as `loader` — functions are wrapped into simple loaders automatically
Example fix
// before
const loader = { loadEntry, loadCollection }; // no load()
collections.posts = { loader };
// after
const loader = {
async load(context) {
// read entries and store them via context.store
},
};
collections.posts = defineCollection({ loader }); Defensive patterns
Strategy: type-guard
Type guard
function isBuildTimeLoader(loader) {
return typeof loader === 'function' || typeof loader?.load === 'function';
}
if (!isBuildTimeLoader(collection.loader)) {
// object without load() — either implement load() or move the collection to live.config.ts
throw new TypeError('collection loader must be a function or an object with load()');
} Prevention
- Always define collections through `defineCollection` so loader shape is validated at config load, not at sync time
- Type loaders against the content-layer loader interface (a `load(context)` method) in custom code
- When switching a collection between live and build-time, move the whole definition between config files — never just the loader
When it happens
Trigger: A collections config built programmatically (objects assembled without `defineCollection`, or cast to bypass its checks) whose loader implements `loadEntry`/`loadCollection` but not `load`; a hand-written loader missing the `load` method; a `loader: {}` typo.
Common situations: Configs constructed dynamically or imported from JS modules that skip defineCollection validation; switching a loader type while a stale build cache references the old shape; custom loaders authored without the `load` method.
Related errors
- A content collection is defined with legacy features (e.g…
- ContentLoaderInvalidDataError
- ContentLoaderReturnsInvalidId
- ExpectedImageOptions
- Live content collections must be defined in…
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/0885c1b5fc6495de.
Report an issue: GitHub.
Appendix: source
Thrown at packages/astro/src/content/content-layer.ts:343
_internal: {
rawData: undefined,
filePath,
},
},
{ ...collection, schema },
false,
),
loaderName,
refreshContextData: options?.context,
});
if ('loader' in collection) {
if (typeof collection.loader === 'function') {
return simpleLoader(collection.loader as CollectionLoader<{ id: string }>, context);
}
if (!collection.loader?.load) {
throw new Error(`Collection loader for ${name} does not have a load method`);
}
return collection.loader.load(context);
}
}),
);
this.#validateReferences(contentConfig.config.collections, logger);
await fs.mkdir(this.#settings.config.cacheDir, { recursive: true });
await fs.mkdir(this.#settings.dotAstroDir, { recursive: true });
const assetImportsFile = new URL(ASSET_IMPORTS_FILE, this.#settings.dotAstroDir);
await this.#store.writeAssetImports(assetImportsFile);
const modulesImportsFile = new URL(MODULES_IMPORTS_FILE, this.#settings.dotAstroDir);
await this.#store.writeModuleImports(modulesImportsFile);
await this.#store.waitUntilSaveComplete();
logger.info('Synced content');
if (this.#settings.config.experimental.contentIntellisense) {
await this.regenerateCollectionFileManifest();
}View on GitHub (pinned to 52e6c34790)