vectordotdev/vector · error

Unexpected fragment path

Error message

Unexpected fragment path: {}

What it means

For every added or modified fragment, the checker extracts the file name to validate it. If the diff reports a path with no usable file name (e.g. a directory entry or a path that is not valid UTF-8 as a file name), it cannot proceed and bails with this error.

Solutions

  1. Find the offending staged path: `git diff --name-only --diff-filter=A <merge-base>` and look for weird/non-UTF-8 names
  2. Rename or remove the bad file: `git rm --cached '<bad path>'` and re-create it with an ASCII slug via `vdev changelog new`
  3. Avoid non-ASCII filenames in changelog.d/

Example fix

# before
changelog.d/fülltext_fix.md  # non-UTF-8-safe pipeline chokes
# after
git mv "changelog.d/fülltext_fix.md" changelog.d/fulltext_fix.md
Defensive patterns

Strategy: validation

Validate before calling

for (const f of addedFragments) { if (!path.basename(f)) throw new Error(`unexpected fragment path: ${f}`); }

Type guard

const hasFileName = (p) => Boolean(path.basename(p)) && Buffer.from(path.basename(p), "utf8").toString("utf8") === path.basename(p);

Try / catch

try { runCheck(); } catch (e) { if (/Unexpected fragment path/.test(e.message)) { renameBadFragmentFile(e.message); } throw e; }

Prevention

When it happens

Trigger: `git diff --name-only` yields a fragment path whose final component is not valid UTF-8 (non-ASCII bytes) or is empty/directory-like, and that path survived the is_real_fragment filter.

Common situations: Creating a fragment file with non-UTF-8 characters in its name (e.g. via a script or copy-paste of unicode); tooling that stages directory paths instead of files.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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

Appendix: source

Thrown at vdev/src/commands/check/changelog_fragments.rs:74

            );
        }
        if added_real.len() > self.max_fragments {
            bail!(
                "Too many changelog fragments ({} > {}).",
                added_real.len(),
                self.max_fragments
            );
        }

        // Every touched fragment (added or modified) must pass the schema check.
        let modified: Vec<PathBuf> = diff_fragments(&self.merge_base, "M")?
            .into_iter()
            .filter(is_real_fragment)
            .collect();
        let expected_parent = std::path::Path::new(CHANGELOG_DIR);
        for path in added_real.iter().chain(modified.iter()) {
            let Some(name) = path.file_name().and_then(|s| s.to_str()) else {
                bail!("Unexpected fragment path: {}", path.display());
            };
            if path.parent() != Some(expected_parent) {
                bail!(
                    "invalid fragment path '{}': fragments must live directly under {CHANGELOG_DIR}/, not in a subdirectory.",
                    path.display()
                );
            }
            info!("Validating '{name}'");
            let fragment_type = validate_filename(name)?;
            validate_contents(&repo_root.join(path), name, fragment_type)?;
        }

        // Cross-fragment check: derived-or-explicit anchors across every breaking fragment
        // currently in `changelog.d/` must be unique and non-empty. Catches conflicts at CI
        // time rather than at release time (when a partial CUE may already exist).
        validate_breaking_anchor_set(&changelog_dir)?;

        info!("changelog additions are valid.");

View on GitHub (pinned to bdb87aeaa4)