nikivdev/code · error
missing PR title (expected a non-empty line under `# Title`)
Error message
missing PR title (expected a non-empty line under `# Title`)
What it means
parse_title_body parses a PR description file that must contain a `# Title` heading followed by a non-empty title line, plus a body. It throws this error when the title section is absent or contains only whitespace, because a PR cannot be created or edited without a title.
Source
Thrown at src/pr_edit.rs:615
}
if l.trim() == "# Description" {
while let Some(nl) = lines.peek() {
if nl.trim().is_empty() {
lines.next();
} else {
break;
}
}
for rest in lines {
body_lines.push(rest.to_string());
}
break;
}
}
let title = title.unwrap_or_default().trim().to_string();
if title.is_empty() {
bail!("missing PR title (expected a non-empty line under `# Title`)");
}
let body = body_lines.join("\n").trim_end().to_string();
Ok((title, body))
}
fn write_index(dir: &Path, idx: &IndexFile) -> Result<()> {
let path = dir.join(INDEX_FILENAME);
let json = serde_json::to_string_pretty(idx)?;
std::fs::write(path, json)?;
Ok(())
}
/// Best-effort helper for other codepaths (e.g. `f pr open edit`) to register mappings for files
/// that don't (yet) have frontmatter.
pub fn index_upsert_file(path: &Path, repo: &str, pr: u64) -> Result<()> {
let dir = pr_edit_dir()?;
std::fs::create_dir_all(&dir)?;
let mut idx = load_index(&dir).unwrap_or_default();View on GitHub (pinned to a747e741ae)
Solutions
- Add a non-empty title line directly under the `# Title` heading in the PR file
- Verify the heading is exactly `# Title` so the parser recognizes the section
- Re-sync or restore the file from the template if the title section was accidentally deleted
- Trim stray whitespace-only lines under the heading
Example fix
// before # Title Some body text... // after # Title Add support for retrying failed uploads Some body text...
Defensive patterns
Strategy: validation
Validate before calling
let content = std::fs::read_to_string("PR.md")?;
let has_title = content.lines()
.collect::<Vec<_>>()
.windows(2)
.any(|w| w[0].trim() == "# Title" && !w[1].trim().is_empty());
if !has_title { anyhow::bail!("PR file lacks a title under `# Title`"); } Type guard
fn has_title_section(content: &str) -> bool {
let mut lines = content.lines().map(str::trim);
while let Some(line) = lines.next() {
if line == "# Title" {
return lines.next().map_or(false, |t| !t.is_empty());
}
}
false
} Try / catch
match parse_title_body(&content) {
Ok((title, body)) if !title.is_empty() => sync_file(title, body)?,
Err(e) => eprintln!("Fix PR file first: {e}"),
} Prevention
- Always keep a non-empty line directly under `# Title` in PR description files
- Start from the official template rather than a blank file
- Lint PR markdown files for required sections before syncing
- Avoid whitespace-only placeholder lines under the heading
When it happens
Trigger: Running sync_file on a PR markdown file where the `# Title` heading is missing, or the line(s) under it are empty/whitespace only.
Common situations: Hand-edited PR description files where the user deleted the title; templates with a placeholder like `# Title` and nothing beneath it; automated tools that regenerated the file without the title; trailing whitespace that looks like content.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- unsupported `f pr preview --mode` value: {other}
- No prompt provided. Usage: f agents run {} "your prompt here
- agent run requires a non-empty query
- prompt is empty
- archive message cannot be empty
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/c2a1463c6d6b1837.
Report an issue: GitHub.