sigoden/aichat · error

Unable to save the role with arguments (whose name contains…

Error message

Unable to save the role with arguments (whose name contains '#')

What it means

Raised by save_role() when the current role uses argument placeholders (its name/prompt contains '#' argument markers). Such roles are ephemeral by design; persisting a role with unresolved arguments would bake in invalid placeholders, so saving is refused. The input at fault is a role with has_args() true.

Solutions

  1. Remove the argument placeholders from the prompt before saving
  2. Save the role under a plain name without arguments and pass arguments at usage time
  3. Use upsert_role with an explicit, argument-free definition instead
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src/config/mod.rs:999 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at src/config/mod.rs:999

        self.use_role(&name)
    }

    pub fn upsert_role(&mut self, name: &str) -> Result<()> {
        let role_path = Self::role_file(name);
        ensure_parent_exists(&role_path)?;
        let editor = self.editor()?;
        edit_file(&editor, &role_path)?;
        if self.working_mode.is_repl() {
            println!("✓ Saved the role to '{}'.", role_path.display());
        }
        Ok(())
    }

    pub fn save_role(&mut self, name: Option<&str>) -> Result<()> {
        let mut role_name = match &self.role {
            Some(role) => {
                if role.has_args() {
                    bail!("Unable to save the role with arguments (whose name contains '#')")
                }
                match name {
                    Some(v) => v.to_string(),
                    None => role.name().to_string(),
                }
            }
            None => bail!("No role"),
        };
        if role_name == TEMP_ROLE_NAME {
            role_name = Text::new("Role name:")
                .with_validator(|input: &str| {
                    let input = input.trim();
                    if input.is_empty() {
                        Ok(Validation::Invalid("This name is required".into()))
                    } else if input == TEMP_ROLE_NAME {
                        Ok(Validation::Invalid("This name is reserved".into()))
                    } else {
                        Ok(Validation::Valid)

View on GitHub (pinned to 82976d349a)