rust-lang/rust · error · anyhow::Error

extraction of the title failed

Error message

extraction of the title failed

What it means

Thrown by rust-analyzer's AsciiDoc-to-Markdown converter (convert_asciidoc_to_markdown) inside process_block_with_title. After consuming a line that the dispatch loop routed here because it started with '.', the code calls strip_prefix('.') to extract the caption text. Because the function is only entered when the peeked line starts with '.', this branch is effectively unreachable — it would only fire from a bug in the converter's dispatch or a race between peek() and next() on the underlying iterator.

Source

Thrown at src/tools/rust-analyzer/xtask/src/publish/notes.rs:184

            self.output.push('\n');
            while let Some(line) = self.iter.next() {
                let line = line?;
                if line == LISTING_DELIMITER {
                    self.write_line("```", level);
                    return Ok(());
                } else {
                    self.write_line(&line, level);
                }
            }
            bail!("listing block is not terminated")
        }
        bail!("not a listing block")
    }

    fn process_block_with_title(&mut self, level: usize) -> anyhow::Result<()> {
        if let Some(Ok(line)) = self.iter.next() {
            let title =
                line.strip_prefix('.').ok_or_else(|| anyhow!("extraction of the title failed"))?;

            let line = self
                .iter
                .peek()
                .ok_or_else(|| anyhow!("target block for the title is not found"))?;
            let line = line.as_deref().map_err(|e| anyhow!("{e}"))?;
            if line.starts_with(IMAGE_BLOCK_PREFIX) {
                return self.process_image_block(Some(title), level);
            } else if line.starts_with(VIDEO_BLOCK_PREFIX) {
                return self.process_video_block(Some(title), level);
            } else {
                bail!("title for that block type is not supported");
            }
        }
        bail!("not a title")
    }

    fn process_image_block(&mut self, caption: Option<&str>, level: usize) -> anyhow::Result<()> {

View on GitHub (pinned to 7088e4b63a)

Solutions

  1. Inspect the input AsciiDoc around the failing line — confirm the line actually starts with '.' and is followed by an image:: or video:: block.
  2. If you are editing the converter, verify that process_block_with_title is only called from branches that already checked line.starts_with('.').
  3. Add a debug assertion or test fixture that reproduces the exact input to isolate the dispatch mismatch.
  4. Report upstream if the error fires without any converter modifications — it indicates a genuine bug in peek/next consistency.

Example fix

// before (buggy dispatch routing a non-'.' line into the title handler):
} else if line.starts_with('.') {
    self.process_block_with_title(0)?;
// after (guard the invariant explicitly):
} else if line.starts_with('.') {
    debug_assert!(line.starts_with('.'), "dispatch invariant broken");
    self.process_block_with_title(0)?;
Defensive patterns

Strategy: validation

Validate before calling

// Before calling convert_asciidoc_to_markdown, validate that the
// AsciiDoc input doesn't have orphan block-title lines.
fn validate_no_dangling_titles(input: &str) -> Result<(), String> {
    let lines: Vec<&str> = input.lines().collect();
    for (i, line) in lines.iter().enumerate() {
        if line.starts_with('.') && !line.starts_with("..") {
            let next = lines.get(i + 1).copied().unwrap_or("");
            if !next.starts_with("image::") && !next.starts_with("video::") {
                return Err(format!("dangling block title at line {}: '{}'", i + 1, line));
            }
        }
    }
    Ok(())
}

Try / catch

// Rust: handle the anyhow::Result from convert_asciidoc_to_markdown
match convert_asciidoc_to_markdown(std::io::Cursor::new(&input)) {
    Ok(markdown) => println!("{}", markdown),
    Err(e) => eprintln!("AsciiDoc conversion failed: {e:#}"),
}

Prevention

When it happens

Trigger: Calling convert_asciidoc_to_markdown on input where the main loop (process, line 39-40) or a list-continuation branch (line 116-117) peeks a line starting with '.', but the subsequently consumed line from self.iter.next() does not actually start with '.'. This can only happen if the AsciiDoc source changes between peek and next or the dispatch logic is modified incorrectly.

Common situations: Maintainer editing the AsciiDoc converter dispatch logic and introducing a routing bug; feeding a malformed .adoc file that causes the peek/next invariant to break; a test fixture with a stray '.' line that the converter mishandles.

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/7e0b0ff42827670a. Report an issue: GitHub.