spacedriveapp/spacedrive · error
Invalid event type: {}
Error message
Invalid event type: {} What it means
The sync event log row mapper (core/src/infra/sync/event_log/logger.rs:192) converts the sync_event_log.event_type TEXT column back into SyncEventType via a hand-written from_str that only accepts exact snake_case tokens: state_transition, backfill_session_started, backfill_session_completed, backfill_session_failed, catch_up_session_started, catch_up_session_completed, batch_ingestion, backfill_request_sent, backfill_request_received, backfill_response_sent, peer_connected, peer_disconnected, sync_error. Any other string fails the whole row read (e.g. get_events page) with this anyhow error.
Source
Thrown at core/src/infra/sync/event_log/logger.rs:192
let timestamp_str: String = row.try_get("", "timestamp")?;
let device_id_str: String = row.try_get("", "device_id")?;
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(×tamp_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
- Check which tokens exist: `SELECT DISTINCT event_type FROM sync_event_log ORDER BY timestamp DESC;` and compare with the list above.
- Delete or re-label unknown rows: DELETE FROM sync_event_log WHERE event_type NOT IN ('state_transition','backfill_session_started',...); (event log is diagnostic data, safe to prune).
- If you control the enum, extend SyncEventType::from_str with the new token or add a catch-all Unknown variant so old builds degrade instead of failing.
- Purge old events with the existing retention query (logger.rs DELETE FROM sync_event_log WHERE timestamp < ?).
Example fix
// before: from_str returns None -> anyhow error for the page
"sync_error_occurred" => unreachable!(),
// after: add the token (or map unknowns)
pub fn from_str(s: &str) -> Option<Self> {
match s {
// ... existing arms ...
"sync_error_occurred" | "sync_error" => Some(Self::SyncError),
_ => None,
}
} Defensive patterns
Strategy: validation
Validate before calling
// read-side tolerant parsing: accept known tokens, mark the rest unknown
fn parse_event_type(s: &str) -> Option<SyncEventType> {
SyncEventType::from_str(s)
} Type guard
fn is_known_event_type(s: &str) -> bool {
SyncEventType::from_str(s).is_some()
} Try / catch
// per-row catch keeps one unknown token from failing the whole event page
let event_type = match SyncEventType::from_str(&event_type_str) {
Some(t) => t,
None => {
tracing::warn!(event_type = %event_type_str, "unknown event type, skipping row");
continue;
}
}; Prevention
- Write event_type only via SyncEventType::as_str().
- When adding event types, also handle them in from_str of older readers or purge old rows.
- Treat sync_event_log as disposable diagnostic data; prune with the retention DELETE on version upgrades.
When it happens
Trigger: Reading sync_event_log rows containing an event_type token this build does not know: rows written by a daemon from a different version that added/renamed event types, or rows inserted manually. Note the row read is all-or-nothing: one unknown token fails the entire query result.
Common situations: Opening the sync event viewer after switching daemon versions; a newer peer device writing to a shared DB; QA inserting fixture rows with wrong tokens; refactoring event names without a data migration.
Related errors
- Invalid category: {}
- Invalid severity: {}
- Failed to deserialize sync response: {}
- Failed to deserialize sync response: {}
- Failed to query library devices: {}
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/bfc2a8eb96a1afef.
Report an issue: GitHub.