zeroclaw-labs/zeroclaw · error

Invalid project key '{key}'. Expected ASCII alphanumeric, e.

Error message

Invalid project key '{key}'. Expected ASCII alphanumeric, e.g. PROJ

What it means

Local format validation of a project key used by create_ticket: the key must be non-empty and every character ASCII alphanumeric. Notably it rejects '-' and other punctuation, so passing a full issue key ("PROJ-42") here fails. It runs before the summary/issue_type checks and before any network call.

Source

Thrown at crates/zeroclaw-tools/src/jira_tool.rs:1328

    });
    if valid {
        Ok(())
    } else {
        anyhow::bail!(
            "Invalid issue key '{key}'. Expected format: PROJECT-123 (e.g. PROJ-42, proj-42)"
        )
    }
}

/// Validates that `key` matches the Jira project key format. Same character
/// class as the project portion of `validate_issue_key` so the two stay in
/// step.
fn validate_project_key(key: &str) -> anyhow::Result<()> {
    let valid = !key.is_empty() && key.chars().all(|c| c.is_ascii_alphanumeric());
    if valid {
        Ok(())
    } else {
        anyhow::bail!("Invalid project key '{key}'. Expected ASCII alphanumeric, e.g. PROJ")
    }
}

// ── Response shaping ──────────────────────────────────────────────────────────

/// Safely extracts the first 10 characters (date prefix) from a string.
/// Returns the full string if it is shorter than 10 characters instead of
/// panicking on out-of-bounds slice indexing.
fn date_prefix(s: &str) -> &str {
    s.get(..10).unwrap_or(s)
}

fn shape_basic(raw: &Value) -> Value {
    let f = &raw["fields"];
    let rf = &raw["renderedFields"];

    // Build a lookup map from comment ID → rendered body for O(1) access
    // instead of scanning the rendered array for each comment (O(n²)).

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Pass only the project key, e.g. "PROJ", not an issue key.
  2. Make the project key a required, trimmed configuration value and fail fast at startup if it is blank.
  3. Validate the format in your own layer before calling create_ticket (see below).

Example fix

// before
jira.create_ticket("PROJ-42", "Bug", "Crash on save", None, None, None, None).await?; // -> error: issue key passed as project

// after
jira.create_ticket("PROJ", "Bug", "Crash on save", None, None, None, None).await?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_project_key(key: &str) -> bool {
    !key.is_empty() && key.chars().all(|c| c.is_ascii_alphanumeric())
}
if !is_valid_project_key(project.trim()) { anyhow::bail!("bad project key"); }

Prevention

When it happens

Trigger: Calling create_ticket with an issue key instead of a project key ("PROJ-42"); an empty project string from a missing config value; project keys with punctuation that some legacy Jira instances allow; whitespace in the key from untrimmed config.

Common situations: Config files storing the default project as blank; agents conflating project key and issue key; migrating from instances whose project keys contain characters Jira no longer permits.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/64ebf84644d7529a. Report an issue: GitHub.