sigoden/aichat · error

No macro

Error message

No macro

What it means

Thrown by GlobalConfig::new_macro() when `self.macro_flag` is true, i.e. the tool is already running in the middle of macro creation/editing. It prevents recursively or erroneously opening a new macro editor while a macro operation is in progress.

Solutions

  1. Do not invoke new_macro while a macro operation is already in progress.
  2. Clear/complete the current macro session (macro_flag reset) before creating another macro.
  3. Remove macro-creation commands from prelude or session replay content.

Example fix

// before
config.new_macro("greet")?;
// after
if !config.read().macro_flag {
    config.write().new_macro("greet")?;
} else {
    eprintln!("A macro operation is already in progress");
}
Defensive patterns

Strategy: validation

Validate before calling

if config.read().macro_flag { return Err(anyhow!("macro operation already in progress")); }

Try / catch

match config.new_macro(name) { Err(e) if e.to_string() == "No macro" => eprintln!("Cannot nest macro creation"), other => other?, }

Prevention

When it happens

Trigger: Calling new_macro(name) while macro_flag is set — typically by invoking the macro-creation command from inside a macro/prelude-driven session or re-entrant command evaluation.

Common situations: A prelude (repl_prelude/cmd_prelude) or session state referencing macro creation while macro mode is already active; scripting nested macro edits.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of sigoden/aichat@82976d349a (2026-09-09). Data as JSON: /api/errors/cbfd20d6b7ba587e. Report an issue: GitHub.

Appendix: source

Thrown at src/config/mod.rs:1596

        list_file_names(Self::macros_dir(), ".yaml")
    }

    pub fn load_macro(name: &str) -> Result<Macro> {
        let path = Self::macro_file(name);
        let err = || format!("Failed to load macro '{name}' at '{}'", path.display());
        let content = read_to_string(&path).with_context(err)?;
        let value: Macro = serde_yaml::from_str(&content).with_context(err)?;
        Ok(value)
    }

    pub fn has_macro(name: &str) -> bool {
        let names = Self::list_macros();
        names.contains(&name.to_string())
    }

    pub fn new_macro(&mut self, name: &str) -> Result<()> {
        if self.macro_flag {
            bail!("No macro");
        }
        let ans = Confirm::new("Create a new macro?")
            .with_default(true)
            .prompt()?;
        if ans {
            let macro_path = Self::macro_file(name);
            ensure_parent_exists(&macro_path)?;
            let editor = self.editor()?;
            edit_file(&editor, &macro_path)?;
        } else {
            bail!("No macro");
        }
        Ok(())
    }

    pub fn apply_prelude(&mut self) -> Result<()> {
        if self.macro_flag || !self.state().is_empty() {
            return Ok(());

View on GitHub (pinned to 82976d349a)