spacedriveapp/spacedrive · error

Invalid category: {}

Error message

Invalid category: {}

What it means

Row mapper at core/src/infra/sync/event_log/logger.rs:194 parses sync_event_log.category via EventCategory::from_str, which accepts exactly four snake_case values: lifecycle, data_flow, network, error. Any other string in the category column makes the whole event-log read (row_to_event) fail with this error.

Source

Thrown at core/src/infra/sync/event_log/logger.rs:194

		let event_type_str: String = row.try_get("", "event_type")?;
		let category_str: String = row.try_get("", "category")?;
		let severity_str: String = row.try_get("", "severity")?;
		let summary: String = row.try_get("", "summary")?;
		let details_str: Option<String> = row.try_get("", "details").ok();
		let correlation_id_str: Option<String> = row.try_get("", "correlation_id").ok();
		let peer_device_id_str: Option<String> = row.try_get("", "peer_device_id").ok();
		let model_types_str: Option<String> = row.try_get("", "model_types").ok();
		let record_count: Option<i64> = row.try_get("", "record_count").ok();
		let duration_ms: Option<i64> = row.try_get("", "duration_ms").ok();

		Ok(SyncEventLog {
			id: Some(id),
			timestamp: DateTime::parse_from_rfc3339(&timestamp_str)?.with_timezone(&Utc),
			device_id: Uuid::parse_str(&device_id_str)?,
			event_type: SyncEventType::from_str(&event_type_str)
				.ok_or_else(|| anyhow::anyhow!("Invalid event type: {}", event_type_str))?,
			category: EventCategory::from_str(&category_str)
				.ok_or_else(|| anyhow::anyhow!("Invalid category: {}", category_str))?,
			severity: EventSeverity::from_str(&severity_str)
				.ok_or_else(|| anyhow::anyhow!("Invalid severity: {}", severity_str))?,
			summary,
			details: details_str
				.as_ref()
				.and_then(|s| serde_json::from_str(s).ok()),
			correlation_id: correlation_id_str
				.as_ref()
				.and_then(|s| Uuid::parse_str(s).ok()),
			peer_device_id: peer_device_id_str
				.as_ref()
				.and_then(|s| Uuid::parse_str(s).ok()),
			model_types: model_types_str.map(|s| s.split(',').map(|t| t.to_string()).collect()),
			record_count: record_count.map(|c| c as u64),
			duration_ms: duration_ms.map(|d| d as u64),
		})
	}

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. Enumerate values: `SELECT DISTINCT category FROM sync_event_log;` and compare to lifecycle/data_flow/network/error.
  2. Prune or normalize bad rows (event log is diagnostic, pruning is safe): UPDATE sync_event_log SET category='error' WHERE category='errors'; or DELETE them.
  3. When renaming categories in code, add a legacy arm to EventCategory::from_str or ship a data migration.

Example fix

# before
sqlite> SELECT DISTINCT category FROM sync_event_log;
errors

# after
sqlite> UPDATE sync_event_log SET category='error' WHERE category='errors';
Defensive patterns

Strategy: validation

Validate before calling

// reject fixture/manual writes whose category is not a real token
fn valid_category(s: &str) -> bool {
    EventCategory::from_str(s).is_some()
}

Type guard

fn parse_category(s: &str) -> Option<EventCategory> {
    EventCategory::from_str(s)
}

Try / catch

// skip rows with unknown categories instead of failing the listing
let category = match EventCategory::from_str(&category_str) {
    Some(c) => c,
    None => { tracing::warn!(category = %category_str, "unknown category"); continue; }
};

Prevention

When it happens

Trigger: A sync_event_log row whose category is not one of the four tokens: written by a different core version, inserted by fixtures/scripts, or hand-edited. Because category is written by EventCategory::as_str(), core-generated rows are always valid, so this almost always means external writes or version skew.

Common situations: QA seeding the event log with made-up categories; a build that renamed 'data_flow' to something else; reading a DB created by a dev branch.

Related errors


AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16). Data as JSON: /api/errors/d78d0273113af18d. Report an issue: GitHub.