affaan-m/ECC · error

Context graph observation type cannot be empty

Error message

Context graph observation type cannot be empty

What it means

add/upsert of a context-graph observation validates observation_type first: a blank (after trim) type raises `Context graph observation type cannot be empty`. The type categorizes observations (e.g. "note", "error", "decision") and must be non-empty.

Solutions

  1. Supply an explicit observation type constant for each insert site.
  2. Default to a well-known catch-all type (e.g. "general") instead of empty when the source lacks a category.
  3. Validate/trim at the call boundary and reject or skip blank types.
  4. Fix upstream mapping so optional categories become Option<String>, not empty strings.

Example fix

// before
let kind = source_category.unwrap_or("");
store.add_context_graph_observation(session_id, kind, priority, pinned, &summary, &details)?;
// after
let kind = source_category.unwrap_or("general");
store.add_context_graph_observation(session_id, kind, priority, pinned, &summary, &details)?;
Defensive patterns

Strategy: validation

Validate before calling

const kind = (observationType ?? 'general').trim() || 'general';
await api.addContextGraphObservation(sessionId, kind, priority, pinned, summary, details);

Type guard

function hasObservationType(v) { return typeof v === 'string' && v.trim().length > 0; }

Try / catch

try {
    store.add_context_graph_observation(session_id, &kind, priority, pinned, &summary, &details)?;
} catch (e) {
    if (String(e).includes('observation type cannot be empty')) {
        // retry with fallback category
        store.add_context_graph_observation(session_id, "general", priority, pinned, &summary, &details)?;
    } else throw e;
}

Prevention

When it happens

Trigger: Calling the observation API with observation_type = "" or " " — typically when the type is derived from a plugin/category field that is optional or defaulted to empty.

Common situations: Importing observations from external logs without a category field; UI submissions with an unset type selector mapped to empty string; scripted bulk inserts missing the column.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/85dbca38b02397fc. Report an issue: GitHub.

Appendix: source

Thrown at ecc2/src/session/store.rs:3380

        Ok(Some(ContextGraphEntityDetail {
            entity,
            outgoing,
            incoming,
        }))
    }

    pub fn add_context_observation(
        &self,
        session_id: Option<&str>,
        entity_id: i64,
        observation_type: &str,
        priority: ContextObservationPriority,
        pinned: bool,
        summary: &str,
        details: &BTreeMap<String, String>,
    ) -> Result<ContextGraphObservation> {
        if observation_type.trim().is_empty() {
            return Err(anyhow::anyhow!(
                "Context graph observation type cannot be empty"
            ));
        }
        if summary.trim().is_empty() {
            return Err(anyhow::anyhow!(
                "Context graph observation summary cannot be empty"
            ));
        }

        let now = chrono::Utc::now().to_rfc3339();
        let details_json = serde_json::to_string(details)?;
        self.conn.execute(
            "INSERT INTO context_graph_observations (
                session_id, entity_id, observation_type, priority, pinned, summary, details_json, created_at
             ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)",
            rusqlite::params![
                session_id,
                entity_id,

View on GitHub (pinned to 8321021c54)