{"record":{"id":"25f17f2ab6db4e4f","repo":"withastro/astro","slug":"a-content-collection-is-defined-with-legacy-featur","errorCode":null,"errorMessage":"A content collection is defined with legacy features (e.g. missing a `loader` or has a `type`). Check your collection definitions in ${importerFilename ?? 'your content config file'} to ensure that all collections are defined using the current properties.","messagePattern":"A content collection is defined with legacy features \\(e\\.g\\. missing a `loader` or has a `type`\\)\\. Check your collection definitions in (.+?) to ensure that all collections are defined using the current properties\\.","errorType":"exception","errorClass":"AstroUserError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/content/config.ts","lineNumber":195,"sourceCode":"export function defineCollection<\n\tS extends BaseSchema,\n\tTLoader extends LoaderConstraint<{ id: string }> = LoaderConstraint<{ id: string }>,\n>(config: CollectionConfig<S, TLoader>): CollectionConfig<S, TLoader> {\n\tconst importerFilename = getImporterFilename();\n\n\tif (importerFilename?.includes('live.config')) {\n\t\tthrow new AstroError({\n\t\t\t...AstroErrorData.LiveContentConfigError,\n\t\t\tmessage: AstroErrorData.LiveContentConfigError.message(\n\t\t\t\t'Collections in a live config file must use `defineLiveCollection`.',\n\t\t\t\timporterFilename,\n\t\t\t),\n\t\t});\n\t}\n\n\tif ('loader' in config) {\n\t\tif (config.type && config.type !== CONTENT_LAYER_TYPE) {\n\t\t\tthrow new AstroUserError(\n\t\t\t\t`A content collection is defined with legacy features (e.g. missing a \\`loader\\` or has a \\`type\\`). Check your collection definitions in ${importerFilename ?? 'your content config file'} to ensure that all collections are defined using the current properties.`,\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\ttypeof config.loader === 'object' &&\n\t\t\ttypeof config.loader.load !== 'function' &&\n\t\t\t('loadEntry' in config.loader || 'loadCollection' in config.loader)\n\t\t) {\n\t\t\tthrow new AstroUserError(\n\t\t\t\t`Live content collections must be defined in \"src/live.config.ts\" file. Check the loaders used in \"${importerFilename ?? 'your content config file'}\" to ensure you are not using a live loader to define a build-time content collection.`,\n\t\t\t);\n\t\t}\n\t\tconfig.type = CONTENT_LAYER_TYPE;\n\t}\n\tif (!config.type) config.type = 'content';\n\treturn config;\n}\n","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/withastro/astro/blob/157c500c38faa7ecf1251adbaeefcd109470d75c/packages/astro/src/content/config.ts#L177-L213","documentation":"In the content-layer API, a collection with a `loader` is a content-layer collection and must not carry a legacy `type`. `defineCollection` throws this AstroUserError when `config.type` is present and is anything other than `'content_layer'`, catching half-migrated configs that combine the legacy (`type: 'content' | 'data'`) and loader-based APIs.","triggerScenarios":"`defineCollection({ type: 'content', loader: glob({...}) })` or `{ type: 'data', loader: file(...) }` in src/content.config.ts — an old Astro 2/3-style definition that gained a loader without dropping `type`.","commonSituations":"Upgrading a project from Astro <=4 to Astro 5, where `type` became optional/inferred and loaders became required; following an old tutorial that includes `type` and adding a loader on top; generated config templates that mix eras.","solutions":["Delete the `type` property — it is inferred (`content_layer`) whenever a loader is present","Audit the collection for other legacy keys per the content-layer migration guide and remove them","Follow the Astro v4 -> v5 content collections migration guide to update all collections at once"],"exampleFix":"// before\nexport const collections = {\n  posts: defineCollection({\n    type: 'content',\n    loader: glob({ pattern: '**/*.md', base: './src/content/posts' }),\n  }),\n};\n\n// after\nexport const collections = {\n  posts: defineCollection({\n    loader: glob({ pattern: '**/*.md', base: './src/content/posts' }),\n  }),\n};","handlingStrategy":"validation","validationCode":"// normalize a migrated collection before defineCollection\nfunction modernizeCollection(config) {\n  if ('loader' in config) {\n    delete config.type; // inferred as 'content_layer' when a loader is present\n  }\n  return config;\n}\nexport const collections = {\n  posts: defineCollection(modernizeCollection(cfg)),\n};","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When adding a `loader` to an old collection, delete `type` in the same edit","Follow the official Astro v5 content-layer migration guide end to end rather than patching piecemeal","Grep content.config.ts for `type:` after any Astro major upgrade to catch leftovers"],"tags":["content-collections","content-layer","migration","legacy-config"],"backgroundTag":"legacy-config-migration","analyzedSha":"157c500c38faa7ecf1251adbaeefcd109470d75c","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}