GitoxideLabs/gitoxide · error

CommentChar must not contain a line ending

Error message

CommentChar must not contain a line ending

What it means

The reword edit document carries enrichment headers, one of which is `CommentChar`. Because comment lines are detected by line-start prefix matching, a comment character containing `\r` or `\n` would corrupt line parsing. `parse` therefore rejects any CommentChar value containing a line ending with this error.

Solutions

  1. Set CommentChar to a single non-line-ending character (e.g. `#`).
  2. Normalize line endings (CRLF → LF) before writing/parsing the document.
  3. Regenerate the edit document via `document()` instead of hand-editing headers.

Example fix

// before (document header with CR leaking in)
CommentChar: #\r
// after (normalize before parsing)
let normalized: Vec<u8> = edited.iter().copied().filter(|&b| b != b'\r').collect();
parse(&normalized)?;
Defensive patterns

Strategy: validation

Validate before calling

fn comment_char_is_safe(value: &[u8]) -> bool {
    !value.contains(&b'\n') && !value.contains(&b'\r')
}

Try / catch

match parse(&edited) {
    Ok(doc) => doc,
    Err(e) if e.to_string().contains("CommentChar") => {
        let sanitized: Vec<u8> = edited.iter().copied().filter(|&b| b != b'\r').collect();
        parse(&sanitized)
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `parse` (via `apply_conflict_reporting`, `parses_the_edit_document`, `document_does_not_repeat_existing_agent_trailers`, or `parses_bare_todo_and_single_line_message_headers`) on a document whose `CommentChar` header value contains a `\r` (checked here) or other line-ending byte.

Common situations: A document generated on/for Windows with CRLF leaking into the header value; a custom comment character mistakenly configured as a multi-character or control-character string; hand-edited enrichment headers.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/00a8b2c8dbadebce. Report an issue: GitHub.

Appendix: source

Thrown at gix-tix/src/edit/reword.rs:359

    out.extend_from_slice(label);
    out.extend_from_slice(
        time.format(gix::date::time::format::ISO8601)
            .context("could not format commit date")?
            .as_bytes(),
    );
    out.push(b'\n');
    Ok(())
}

pub(super) fn parse(input: &[u8]) -> Result<Edit<'_>> {
    let mut parts = input.splitn(6, |byte| *byte == b'\n');
    let author = header(parts.next(), AUTHOR)?;
    let author_time = date(header(parts.next(), AUTHOR_DATE)?, "author")?;
    let committer = header(parts.next(), COMMITTER)?;
    let committer_time = date(header(parts.next(), COMMITTER_DATE)?, "committer")?;
    let comment_char = header(parts.next(), COMMENT_CHAR)?;
    if comment_char.contains(&b'\r') {
        anyhow::bail!("CommentChar must not contain a line ending");
    }
    let remainder = parts.next().context("the enrichment headers are missing")?;
    let mut enrichment = crate::enrich::Headers::default();
    let mut todo_seen = false;
    let mut message_seen = false;
    let mut message_offset = None;
    let mut consumed = 0;
    for line in remainder.lines_with_terminator() {
        consumed += line.len();
        let line = trim_cr(line.strip_suffix(b"\n").unwrap_or(line));
        if line.is_empty() {
            message_offset = Some(consumed);
            break;
        }
        if line.starts_with(comment_char) {
            continue;
        }
        if line == TODO {

View on GitHub (pinned to e73179060b)