GitoxideLabs/gitoxide · error
only recognized assignments remain
Error message
only recognized assignments remain
What it means
When parsing a shell command line like `VAR=value cmd args...`, gix-command splits leading assignments from the command. For each recognized assignment word it expects an assignment_separator was recorded; if an assignment word lacks the separator offset, the parser's earlier classification is inconsistent and it panics.
Solutions
- Upgrade gix-command, as this points to a parser inconsistency likely fixed upstream
- Check the input command string for malformed assignments (e.g. `=value` with an empty name) and sanitize it
- Avoid exotic assignment forms; put environment overrides in normal `NAME=value` form
- If reproducible, file a bug with the exact command string
Example fix
// before
let separator = word.assignment_separator.expect("only recognized assignments remain");
// after
let separator = word.assignment_separator
.ok_or_else(|| message("assignment word without separator"))?; Defensive patterns
Strategy: try-catch
Validate before calling
// Validate input command string uses well-formed NAME=value prefixes:
for word in &assignments { assert!(!word.is_empty() && word.contains(b'=')); } Try / catch
// No recovery from panic; pre-check the parse input or catch via catch_unwind at a boundary: let result = std::panic::catch_unwind(|| parse_and_build(command));
Prevention
- Use standard POSIX-style NAME=value assignments
- Upgrade gix-command to get parser fixes
- Report malformed command strings with a reproduction
- Keep command strings UTF-8 clean before parsing
When it happens
Trigger: Calling Outcome::command_line (or the parse producing it) where a word was counted as an assignment but has assignment_separator == None — an internal parser state inconsistency, e.g. after changes to the assignment recognition logic.
Common situations: Parsing command strings with unusual `=` usage or encoding that confuses the separator detection; library versions where assignment parsing changed.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- shell assignment names contain only ASCII bytes
- ' ' is not a valid configuration key
- Cannot use iter_v1() on index of type
- Cannot use iter_v2() on index of type
- BUG: tries to obtain object id from symbolic target
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/69746aa8bb202d63.
Report an issue: GitHub.
Appendix: source
Thrown at gix-command/src/parse.rs:75
/// Split `input` into leading environment assignments and the command with its arguments.
///
/// Whitespace, quotes, escapes, line continuations, and comments follow POSIX `sh`ell word-splitting rules. Shell
/// expansions and operators are not interpreted. An assignment is recognized only when its name is an unquoted
/// shell identifier. Assignment-only input is rejected because it contains no command to execute. Environment
/// assignment names are strings, while their values, the command, and arguments are converted losslessly to OS
/// strings or rejected if the platform cannot represent them.
pub fn command_line(input: &BStr) -> Result<Outcome, Error> {
let mut words = parse_words(input)?;
let assignment_count = words
.iter()
.take_while(|word| word.assignment_separator.is_some())
.count();
let mut args = words.split_off(assignment_count).into_iter().map(|word| word.value);
let command = into_os_string(args.next().ok_or(Error::MissingCommand)?)?;
let env = words
.into_iter()
.map(|word| {
let separator = word.assignment_separator.expect("only recognized assignments remain");
Ok((
String::from_utf8(word.value[..separator].to_owned())
.expect("shell assignment names contain only ASCII bytes"),
into_os_string(word.value[separator + 1..].to_owned().into())?,
))
})
.collect::<Result<_, Error>>()?;
Ok(Outcome {
env,
command,
args: args.map(into_os_string).collect::<Result<_, _>>()?,
})
}
pub(crate) fn arguments(input: &BStr) -> Result<Vec<OsString>, Error> {
parse_words(input)?
.into_iter()
.map(|word| into_os_string(word.value))View on GitHub (pinned to e73179060b)