{"record":{"id":"65ac6dbed1c00683","repo":"withastro/astro","slug":"string-rootrelativepath-contains-invalid-c","errorCode":null,"errorMessage":"**${String(rootRelativePath)}** contains invalid content:\n- ${e.error.message}","messagePattern":"\\*\\*(.+?)\\*\\* contains invalid content:\n- (.+?)","errorType":"exception","errorClass":"MarkdocError","httpStatus":null,"severity":"error","filePath":"packages/integrations/markdoc/src/content-entry-type.ts","lineNumber":260,"sourceCode":"\tastroConfig: AstroConfig;\n\tfilePath: string;\n}) {\n\tconst validationErrors = Markdoc.validate(ast, markdocConfig).filter((e) => {\n\t\treturn (\n\t\t\t(e.error.level === 'error' || e.error.level === 'critical') &&\n\t\t\t// Ignore `variable-undefined` errors.\n\t\t\t// Variables can be configured at runtime,\n\t\t\t// so we cannot validate them at build time.\n\t\t\te.error.id !== 'variable-undefined' &&\n\t\t\t// Ignore missing partial errors.\n\t\t\t// We will resolve these in `resolvePartials`.\n\t\t\t!(e.error.id === 'attribute-value-invalid' && /^Partial .+ not found/.test(e.error.message))\n\t\t);\n\t});\n\n\tif (validationErrors.length) {\n\t\tconst rootRelativePath = path.relative(fileURLToPath(astroConfig.root), filePath);\n\t\tthrow new MarkdocError({\n\t\t\tmessage: [\n\t\t\t\t`**${String(rootRelativePath)}** contains invalid content:`,\n\t\t\t\t...validationErrors.map((e) => `- ${e.error.message}`),\n\t\t\t].join('\\n'),\n\t\t\tlocation: {\n\t\t\t\t// Error overlay does not support multi-line or ranges.\n\t\t\t\t// Just point to the first line.\n\t\t\t\tline: validationErrors[0].lines[0],\n\t\t\t\tfile: viteId,\n\t\t\t},\n\t\t});\n\t}\n}\n\nfunction getUsedTags(markdocAst: Node) {\n\tconst tags = new Set<string>();\n\tconst validationErrors = Markdoc.validate(markdocAst);\n\t// Hack: run the validator with an empty config and look for 'tag-undefined'.","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/integrations/markdoc/src/content-entry-type.ts#L242-L278","documentation":"The Markdoc integration runs `Markdoc.validate` on each content file at build time and collects real errors, deliberately ignoring `variable-undefined` (runtime-configurable variables) and missing-partial errors (resolved later). Any remaining validation error — bad tag usage, invalid attribute types, malformed structure — fails the build with a per-file bullet list, pointing the error overlay at the first offending line.","triggerScenarios":"A .mdoc file using an unregistered tag, passing a wrong-typed attribute to a schema (e.g. a string where Number is required), or nesting nodes outside their allowed `children` (e.g. block tag inside inline context).","commonSituations":"Authoring mistakes in content collections; schema/config drift after renaming tags or tightening attribute types; contributors unfamiliar with the allowed markup.","solutions":["Read the bulleted Markdoc validation messages — they name the exact tag/attribute problem.","Open the file at the reported line and fix the markup (add the tag to config, fix the attribute value, fix nesting).","If the construct is intentionally valid, adjust the Markdoc config schema (nodes/tags/functions) to permit it.","Re-run the dev server to confirm the overlay clears before rebuilding."],"exampleFix":"{% note type=\"warning\" %}...{% /note %}\n<!-- schema expects type in ['info','danger'] -->\n\n{% note type=\"danger\" %}...{% /note %}","handlingStrategy":"validation","validationCode":"// Validate content in CI with the same engine the build uses\nimport Markdoc from '@markdoc/markdoc';\nimport config from './markdoc.config.mjs';\nimport { globSync } from 'glob';\nimport fs from 'node:fs';\nfor (const f of globSync('src/**/*.mdoc')) {\n  const errors = Markdoc.validate(Markdoc.parse(fs.readFileSync(f, 'utf8')), config)\n    .filter((e) =>\n      e.error.id !== 'variable-undefined' &&\n      !(e.error.id === 'attribute-value-invalid' && /^Partial .+ not found/.test(e.error.message)));\n  if (errors.length) throw new Error(`${f}:\\n${errors.map((e) => `- ${e.error.message}`).join('\\n')}`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run Markdoc.validate as a content-lint CI step mirroring the build's ignore rules.","Keep markdoc.config schemas in sync with the tags authors actually use.","Give content authors the dev-server overlay feedback loop so errors surface on save."],"tags":["markdoc","validation","content-collections","build"],"backgroundTag":"content-validation-failed","analyzedSha":"52e6c34790cc8ac4e69e6135ace06049867e5c4a","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}