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
- Supply an explicit observation type constant for each insert site.
- Default to a well-known catch-all type (e.g. "general") instead of empty when the source lacks a category.
- Validate/trim at the call boundary and reject or skip blank types.
- 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
- Use enum/constant observation types instead of free-form strings where possible.
- Default missing categories to a named fallback, never empty string.
- Trim before calling; reject blank types at the API boundary.
- Document required observation fields for plugin authors.
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
- Context graph observation summary cannot be empty
- Context graph entity name cannot be empty
- Context graph entity type cannot be empty
- Context graph relation type cannot be empty
- -32602
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)