{"record":{"id":"6668753bd0f97aaf","repo":"withastro/astro","slug":"unexpected-problem-adding-heading-ids-to-markdoc-f","errorCode":null,"errorMessage":"Unexpected problem adding heading IDs to Markdoc file. Did you modify the `ctx.headingSlugger` property in your Markdoc config?","messagePattern":"Unexpected problem adding heading IDs to Markdoc file\\. Did you modify the `ctx\\.headingSlugger` property in your Markdoc config\\?","errorType":"exception","errorClass":"MarkdocError","httpStatus":null,"severity":"error","filePath":"packages/integrations/markdoc/src/heading-ids.ts","lineNumber":42,"sourceCode":"}\n\n/*\n\tExpose standalone node for users to import in their config.\n\tAllows users to apply a custom `render: AstroComponent`\n\tand spread our default heading attributes.\n*/\nexport const heading: Schema = {\n\tchildren: ['inline'],\n\tattributes: {\n\t\tid: { type: String },\n\t\tlevel: { type: Number, required: true, default: 1 },\n\t},\n\ttransform(node, config: HeadingIdConfig) {\n\t\tconst { level, ...attributes } = node.transformAttributes(config);\n\t\tconst children = node.transformChildren(config);\n\n\t\tif (!config.ctx?.headingSlugger) {\n\t\t\tthrow new MarkdocError({\n\t\t\t\tmessage:\n\t\t\t\t\t'Unexpected problem adding heading IDs to Markdoc file. Did you modify the `ctx.headingSlugger` property in your Markdoc config?',\n\t\t\t});\n\t\t}\n\t\tconst slug = getSlug(attributes, children, config.ctx.headingSlugger);\n\n\t\tconst render = config.nodes?.heading?.render ?? `h${level}`;\n\n\t\tconst tagProps =\n\t\t\t// For components, pass down `level` as a prop,\n\t\t\t// alongside `__collectHeading` for our `headings` collector.\n\t\t\t// Avoid accidentally rendering `level` as an HTML attribute otherwise!\n\t\t\ttypeof render === 'string'\n\t\t\t\t? { ...attributes, id: slug }\n\t\t\t\t: { ...attributes, id: slug, __collectHeading: true, level };\n\n\t\treturn new Markdoc.Tag(render, tagProps, children);\n\t},","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/withastro/astro/blob/d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca/packages/integrations/markdoc/src/heading-ids.ts#L24-L60","documentation":"The Markdoc `heading` schema transform needs a slugger from `config.ctx.headingSlugger` to generate stable heading IDs. If that property is absent at transform time (the `?` chain returns undefined), the integration throws `MarkdocError` suggesting the user altered `ctx.headingSlugger` in their Markdoc config.","triggerScenarios":"A user `markdocConfig` that overrides `ctx` and removes/renames `headingSlugger`. Calling the heading transform outside the content pipeline where ctx isn't seeded. A custom extension that replaces the `ctx` object passed to Markdoc transforms.","commonSituations":"Customizing Markdoc ctx for heading behavior and accidentally dropping the slugger. Plugin ordering that mutates `config.ctx`. Using a Markdoc version where the integration's ctx contract changed.","solutions":["Avoid overriding or replacing `config.ctx` in your Markdoc config; if you must extend it, preserve the existing `headingSlugger`.","If you supply a custom ctx, ensure `ctx.headingSlugger` is set to a function `(text: string) => string`.","Remove any extension that strips ctx and re-run the build."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"function hasHeadingSlugger(config: any): boolean {\n  return !!(config?.ctx?.headingSlugger) && typeof config.ctx.headingSlugger === 'function';\n}","typeGuard":"function hasSlugger(config: unknown): config is { ctx: { headingSlugger: (s: string) => string } } {\n  return !!config && typeof (config as any)?.ctx?.headingSlugger === 'function';\n}","tryCatchPattern":null,"preventionTips":["Do not override or replace `config.ctx` in Markdoc config.","If extending ctx, spread the existing object to preserve `headingSlugger`.","Test heading rendering after any Markdoc config change."],"tags":["markdoc","headings","configuration","build"],"backgroundTag":null,"analyzedSha":"d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca","analyzedAt":"2026-08-12T13:37:29.035Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}