vectordotdev/vector · error

invalid fragment path

Error message

invalid fragment path '{}': fragments must live directly under {CHANGELOG_DIR}/, not in a subdirectory.

What it means

Fragments must live directly under changelog.d/, not in subdirectories. For each added/modified fragment the checker compares the path's parent against changelog.d and bails if they differ, because filename validation and release tooling only expect top-level fragments.

Solutions

  1. Move the fragment to the top level: `git mv changelog.d/subdir/my_fix.md changelog.d/my_fix.md`
  2. Re-create it at the top level with `vdev changelog new <type> <slug>`
  3. Fix any script that writes fragments into subdirectories of changelog.d/

Example fix

# before
changelog.d/bugs/my_fix.md
# after
git mv changelog.d/bugs/my_fix.md changelog.d/my_fix.md
Defensive patterns

Strategy: validation

Validate before calling

if (path.dirname(fragmentPath) !== "changelog.d") throw new Error("fragments must be directly under changelog.d/");

Type guard

const isTopLevelFragment = (p) => path.posix.dirname(p.replace(/\\/g, "/")) === "changelog.d";

Try / catch

try { runCheck(); } catch (e) { if (/must live directly under/.test(e.message)) { gitMvToTopLevel(parsePath(e.message)); } throw e; }

Prevention

When it happens

Trigger: Adding a fragment in a nested path such as changelog.d/subdir/my_fix.md (or a path whose normalized parent differs from CHANGELOG_DIR) and running the check.

Common situations: Creating fragments inside feature subfolders for organization; scripts writing to changelog.d/<category>/; an editor creating the file in the wrong directory.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

            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.");
        Ok(())
    }
}

View on GitHub (pinned to bdb87aeaa4)