Skip to main content

knowledge_runtime/
error.rs

1/// Error types for the knowledge-runtime crate.
2///
3/// All errors flow through [`RuntimeError`]. Upstream `MemoryError` converts
4/// automatically via `#[from]`.
5#[derive(Debug, thiserror::Error)]
6pub enum RuntimeError {
7    /// Propagated from the upstream semantic-memory store.
8    #[error("memory store error: {0}")]
9    Memory(#[from] semantic_memory::MemoryError),
10
11    /// Configuration is invalid.
12    #[error("invalid config for '{field}': {reason}")]
13    InvalidConfig { field: &'static str, reason: String },
14
15    /// Entity not found in registry.
16    #[error("entity not found: {id}")]
17    EntityNotFound { id: String },
18
19    /// Entity registry is full.
20    #[error("entity registry full (capacity {capacity})")]
21    RegistryFull { capacity: usize },
22
23    /// COR-005: Entity name/alias collision with an existing entity.
24    #[error("entity collision: name '{name}' already registered to {existing_id}, cannot assign to {new_id}")]
25    EntityCollision {
26        name: String,
27        existing_id: crate::ids::EntityId,
28        new_id: crate::ids::EntityId,
29    },
30
31    /// A projection is stale or missing and cannot serve the request.
32    #[error("projection unavailable: {id} ({reason})")]
33    ProjectionUnavailable { id: String, reason: String },
34
35    /// Adapter failed to connect or communicate with the backing store.
36    #[error("adapter error: {0}")]
37    Adapter(String),
38
39    /// Scope dimensions beyond namespace were requested but cannot be fully
40    /// enforced by the upstream adapter. Results may include items outside
41    /// the requested domain/workspace_id/repo_id.
42    #[error("scope not fully enforced: upstream adapter only filters by namespace; unpushed dimensions: {unpushed_dimensions:?}")]
43    ScopeNotFullyEnforced {
44        /// Which scope dimensions could not be pushed to the upstream adapter.
45        unpushed_dimensions: Vec<String>,
46    },
47
48    /// Temporal search was requested but results lack temporal metadata
49    /// (valid_from/valid_to). In strict temporal mode, this is an error
50    /// rather than a silent downgrade.
51    #[error("temporal search not supported: results lack temporal metadata for expression '{temporal_expr}'")]
52    TemporalNotSupported {
53        /// The temporal expression from the query that could not be executed.
54        temporal_expr: String,
55    },
56}
57
58impl RuntimeError {
59    /// Stable string discriminant for programmatic matching.
60    pub fn kind(&self) -> &'static str {
61        match self {
62            Self::Memory(_) => "memory",
63            Self::InvalidConfig { .. } => "invalid_config",
64            Self::EntityNotFound { .. } => "entity_not_found",
65            Self::RegistryFull { .. } => "registry_full",
66            Self::ProjectionUnavailable { .. } => "projection_unavailable",
67            Self::Adapter(_) => "adapter",
68            Self::EntityCollision { .. } => "entity_collision",
69            Self::ScopeNotFullyEnforced { .. } => "scope_not_fully_enforced",
70            Self::TemporalNotSupported { .. } => "temporal_not_supported",
71        }
72    }
73}