vectordotdev/vector · error

Bad fragment filename

Error message

Bad fragment filename: {}

What it means

vdev's changelog fragment parser derives the PR/type suffix by splitting the fragment filename stem on '.'. This error fires when the path has no file stem that can be represented as UTF-8 (e.g. a directory or non-UTF-8 name), so no usable stem exists. It is an early guard before the stricter `<name>.<type>` format check.

Solutions

  1. Inspect the changelog.d directory and remove/rename any non-UTF-8 or path-like entries (e.g. `find changelog.d | grep -vP '[\x00-\x7F]'`).
  2. Ensure only `*.md` files following `<name>.<type>.md` naming live in changelog.d.
  3. Rename the offending file to a plain UTF-8 name before re-running the release command.

Example fix

// before
mv 'changelog.d/fix?pat<04>.md' .   # non-UTF-8 bytes in name
// after
mv 'changelog.d/fix-pat04.md' .
Defensive patterns

Strategy: validation

Validate before calling

fn has_valid_stem(p: &std::path::Path) -> bool {
    p.file_stem().and_then(|n| n.to_str()).is_some()
}
// filter the glob results before running the release command

Prevention

When it happens

Trigger: Calling read_changelog_fragments (during release CUE generation) over a changelog.d directory that contains a path whose file_stem() is None (a directory or '..' path) or whose stem is not valid UTF-8.

Common situations: Globbing picks up a non-UTF-8 filename created by a tool or download; someone placed a directory inside changelog.d; filenames produced on a filesystem with non-UTF-8 bytes.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at vdev/src/commands/release/generate_cue.rs:354

    let mut paths: Vec<PathBuf> = fs::read_dir(dir)?
        .filter_map(|e| e.ok().map(|e| e.path()))
        .filter(|p| p.extension().is_some_and(|x| x == "md"))
        .filter(|p| p.file_name().and_then(|n| n.to_str()) != Some("README.md"))
        .collect();
    paths.sort();
    for path in paths {
        let mut entry = parse_changelog_fragment(&path)?;
        entry.pr_numbers = lookup_pull_requests(repo_root, &path, pull_request_metadata)?;
        entries.push(entry);
    }
    Ok(entries)
}

fn parse_changelog_fragment(path: &Path) -> Result<ChangelogEntry> {
    let stem = path
        .file_stem()
        .and_then(|n| n.to_str())
        .ok_or_else(|| anyhow!("Bad fragment filename: {}", path.display()))?;
    let parts: Vec<&str> = stem.split('.').collect();
    if parts.len() != 2 {
        bail!(
            "Changelog fragment {} is invalid (filename must be <name>.<type>.md)",
            path.display()
        );
    }
    let fragment_type = parts[1];
    let Some(entry) = FRAGMENT_TYPES.iter().find(|t| t.name == fragment_type) else {
        bail!(
            "Changelog fragment {} has unrecognized type '{}' (valid types: {})",
            path.display(),
            fragment_type,
            FRAGMENT_TYPES
                .iter()
                .map(|t| t.name)
                .collect::<Vec<_>>()
                .join("|")

View on GitHub (pinned to 0d4ab78a4f)