vectordotdev/vector · error

Deprecation fragment

Error message

Deprecation fragment {} has unclosed frontmatter

What it means

After finding the opening `---`, `split_frontmatter` locates the closing delimiter via `split_once("\n---")`. If no closing `\n---` sequence exists, the frontmatter block is unterminated and this error is raised with the fragment path. It protects the parser from consuming Markdown body content as YAML metadata.

Solutions

  1. Add a closing `---` on its own line after the frontmatter keys in the file named in the error.
  2. Ensure the closing delimiter is preceded by a newline (frontmatter content must not share its line).
  3. Diff the fragment against a known-good deprecation fragment to confirm both opening and closing fences are present.

Example fix

# before
---
date: 2026-09-15
component: transform/foo

# after
---
date: 2026-09-15
component: transform/foo
---
deprecates the `foo` transform.
Defensive patterns

Strategy: validation

Validate before calling

def has_closed_frontmatter(text):
    t = text.lstrip('\ufeff \t\n\r')
    if not t.startswith('---'):
        return False
    return '\n---' in t[3:]

Prevention

When it happens

Trigger: A deprecation fragment contains an opening `---` line but no second `---` line on its own line (e.g. author wrote frontmatter fields and forgot the closing delimiter, or the closing `---` is on the same line as content).

Common situations: Hand-writing frontmatter and omitting the closing fence; a formatter wrapping/joining the closing `---` with adjacent text; using `----` or indented dashes that still don't form a `\n---` boundary at line start context expected by split_once.

Related errors


AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16). Data as JSON: /api/errors/b270e3f88f05bb3a. Report an issue: GitHub.

Appendix: source

Thrown at vdev/src/utils/deprecation.rs:212

/// Split the raw file contents into the frontmatter string and the body.
/// The file must begin with `---`, and have a closing `---` on its own line.
fn split_frontmatter<'a>(content: &'a str, path: &Path) -> Result<(&'a str, &'a str)> {
    let content = content.trim_start();
    // Advance past the opening `---` (and optional trailing whitespace on that line)
    let after_open = content
        .strip_prefix("---")
        .ok_or_else(|| {
            anyhow!(
                "Deprecation fragment {} must begin with YAML frontmatter (---)",
                path.display()
            )
        })?
        .trim_start_matches([' ', '\t'])
        .trim_start_matches('\n');

    let (frontmatter, rest) = after_open.split_once("\n---").ok_or_else(|| {
        anyhow!(
            "Deprecation fragment {} has unclosed frontmatter",
            path.display()
        )
    })?;
    let rest = rest.trim_start_matches(['\r', '\n']);
    let body = rest.trim_start_matches(['\r', '\n']);

    Ok((frontmatter, body))
}

/// A deprecation that has been enacted (feature removed).
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct EnactedEntry {
    pub what: String,
    pub deprecated_since: String,
    pub removed_in: String,
    #[serde(default, skip_serializing_if = "String::is_empty")]
    pub description: String,

View on GitHub (pinned to bdb87aeaa4)