affaan-m/ECC · error · anyhow::Error

{label} must use key=value form: {value}

Error message

{label} must use key=value form: {value}

What it means

Thrown by parse_key_value_pairs (used for template vars, graph metadata, observation details) when one of the provided string entries has no '=' delimiter at all. The parser requires every entry to be in key=value form; an entry lacking '=' cannot be split into a key and value and is rejected.

Source

Thrown at ecc2/src/main.rs:8593

        to_id,
        &comms::MessageType::TaskHandoff {
            task: from_session.task,
            context,
            priority: comms::TaskPriority::Normal,
        },
    )
}

fn parse_template_vars(values: &[String]) -> Result<BTreeMap<String, String>> {
    parse_key_value_pairs(values, "template vars")
}

fn parse_key_value_pairs(values: &[String], label: &str) -> Result<BTreeMap<String, String>> {
    let mut vars = BTreeMap::new();
    for value in values {
        let (key, raw_value) = value
            .split_once('=')
            .ok_or_else(|| anyhow::anyhow!("{label} must use key=value form: {value}"))?;
        let key = key.trim();
        let raw_value = raw_value.trim();
        if key.is_empty() || raw_value.is_empty() {
            anyhow::bail!("{label} must use non-empty key=value form: {value}");
        }
        vars.insert(key.to_string(), raw_value.to_string());
    }
    Ok(vars)
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::config::Config;
    use crate::session::store::StateStore;
    use crate::session::{Session, SessionMetrics, SessionState};
    use chrono::{Duration, Utc};
    use std::fs;

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Rewrite the offending entry as key=value, e.g. '--var component=billing' instead of '--var component'.
  2. If scripting, construct args with format!("{key}={value}") rather than space-separated tokens.
  3. Quote each entry so the shell does not split on '=' or whitespace.
  4. Re-read the error: it includes the exact value that failed, so fix that one entry.

Example fix

# before
ecc2 run --var component --var area=oauth

# after
ecc2 run --var component=billing --var area=oauth
Defensive patterns

Strategy: validation

Validate before calling

fn is_key_value(entry: &str) -> bool {
    entry.split_once('=').is_some()
}

// validate CLI args up front
for v in &vars {
    if !is_key_value(v) {
        return Err(anyhow!("{v} must be key=value"));
    }
}

Prevention

When it happens

Trigger: Passing a CLI flag like --var component (no '=') or --metadata lang (no '='), or a positional value that omits the delimiter. The label in the message identifies which flag (e.g. 'template vars', 'graph metadata', 'graph observation details').

Common situations: User forgets the '=value' part; shell quoting strips the '='; a script builds args by joining key and value with a space instead of '='; copy-pasting from docs that show the key only.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/d5fe63abc74e5caa. Report an issue: GitHub.