GitoxideLabs/gitoxide · error
must be written as Name
Error message
{field} must be written as Name <email> What it means
Identity headers (Author/Committer) in the edit document must be exactly `Name <email>` — no empty name/email and no trailing time component, because the time is supplied separately as `gix::date::Time`. `actor` parses the value with `gix::actor::SignatureRef::from_bytes` and bails with this error when name or email is empty or the parsed time field is non-empty.
Solutions
- Write the identity as `Name <email>` with both parts non-empty and no timestamp.
- Strip the time component if you copied a raw commit signature line.
- Fill in the author name/email in your git config or pass a complete identity programmatically.
- If `from_bytes` itself fails, the underlying 'could not parse {field} identity' error points at the malformed bytes.
Example fix
// before (document header) Author: <dev@example.com> 1700000000 +0100 // after Author: Jane Dev <dev@example.com>
Defensive patterns
Strategy: validation
Validate before calling
fn identity_well_formed(value: &[u8]) -> bool {
gix::actor::SignatureRef::from_bytes(value)
.ok()
.and_then(|s| s.trim().ok())
.map_or(false, |s| !s.name.is_empty() && !s.email.is_empty() && s.time.is_empty())
} Try / catch
match document_with_author(repo, old_id, author_value, time) {
Ok(doc) => doc,
Err(e) if e.to_string().contains("must be written as Name <email>") => {
eprintln!("Author must look like: Jane Dev <jane@example.com> (no timestamp).");
Err(e)
}
Err(e) => return Err(e),
} Prevention
- Never paste raw git signature lines (which embed a timestamp) into identity headers.
- Ensure git user.name and user.email are configured so defaults are complete.
- Validate identity strings with `SignatureRef::from_bytes` plus the trim checks before writing documents.
When it happens
Trigger: Calling `actor` (via `document_with_author`, `apply_conflict_reporting`, or `apply_message_reporting`) with a `value` like `""`, `"<a@b>"`, `"Name"`, `"Name <>"`, or `"Name <a@b> 1700000000 +0100"` — i.e. anything whose parsed name/email is empty or that carries an embedded timestamp.
Common situations: Copying a raw git signature line (which includes the timestamp) into the document; leaving the author line blank; forgetting the `<email>` part; scripted header generation writing incomplete identities.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- unknown commit header
- lines in ' ' could not be parsed
- Invalid pathspec - path must not be empty, not be excluded…
- Cannot derive archive format from a file without extension
- Format for extension
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/d7146d2c42052eb0.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/reword.rs:458
}
fn trim_cr(line: &[u8]) -> &[u8] {
line.strip_suffix(b"\r").unwrap_or(line)
}
fn date(value: &[u8], field: &str) -> Result<gix::date::Time> {
let value = std::str::from_utf8(value).with_context(|| format!("{field} date is not UTF-8"))?;
gix::date::parse(value, None)
.map_err(|err| anyhow::Error::new(err.into_error()))
.with_context(|| format!("could not parse {field} date"))
}
pub(super) fn actor(value: &[u8], time: gix::date::Time, field: &str) -> Result<gix::actor::Signature> {
let parsed = gix::actor::SignatureRef::from_bytes(value)
.with_context(|| format!("could not parse {field} identity"))?
.trim();
if parsed.name.is_empty() || parsed.email.is_empty() || !parsed.time.is_empty() {
anyhow::bail!("{field} must be written as Name <email>");
}
Ok(gix::actor::Signature {
name: parsed.name.into(),
email: parsed.email.into(),
time,
})
}
#[cfg(test)]
mod tests {
use std::process::Command;
use super::*;
#[test]
fn parses_the_edit_document() -> gix_testtools::Result {
let input = b"Author: A U Thor <author@example.com>\n\
AuthorDate: 2026-08-12 10:20:30 +0200\n\View on GitHub (pinned to e73179060b)