klieo_runlog/error.rs
1//! `RunLogError` — the only error surface for this crate.
2
3use crate::types::StepKind;
4use klieo_core::ids::RunId;
5use thiserror::Error;
6
7/// Errors raised by `klieo-runlog` operations.
8#[non_exhaustive]
9#[derive(Debug, Error)]
10pub enum RunLogError {
11 /// Backend store failure (I/O, serialisation, SQL).
12 #[error("runlog store error: {0}")]
13 Store(String),
14
15 /// `get`/`delete` requested a `run_id` that does not exist.
16 #[error("runlog not found for run_id {0}")]
17 NotFound(RunId),
18
19 /// Projection from `Episode` stream into a `RunLog` aggregate failed.
20 #[error("runlog projection error: {0}")]
21 Projection(String),
22
23 /// Free-form structural replay failure retained for back-compat; all
24 /// in-crate paths now emit a typed variant instead.
25 #[deprecated(note = "use ReplayMismatch, ReplayStep, or NoLlmCall")]
26 #[error("runlog replay error: {0}")]
27 Replay(String),
28
29 /// The `RunLog` carried no `LlmCall` step, so strict `replay` has no final
30 /// assistant text to return.
31 #[error("runlog replay found no LlmCall step")]
32 NoLlmCall,
33
34 /// A replay double produced output that differs from the recording — the
35 /// strict `replay` path's stop condition. Carries both sides so callers
36 /// inspect the divergence without parsing the `Display` string.
37 #[error("runlog replay mismatch at step {step} ({kind:?})")]
38 ReplayMismatch {
39 /// Zero-based index into the source `RunLog.steps`.
40 step: u32,
41 /// Copied from the diverging step; only `LlmCall`/`ToolCall` reach here,
42 /// since other kinds re-issue no I/O on replay.
43 kind: StepKind,
44 /// Recorded output, normalized for comparison (see `flatten_output`).
45 expected: String,
46 /// Replayed output, normalized the same way as `expected`.
47 actual: String,
48 },
49
50 /// A replay double failed to produce output for a step (the LLM/tool call
51 /// errored or a scripted double exhausted) — distinct from a value
52 /// mismatch, which surfaces as `ReplayMismatch` rather than an error.
53 #[error("runlog replay step {step} failed")]
54 ReplayStep {
55 /// Zero-based index into the source `RunLog.steps`.
56 step: u32,
57 /// The `LlmError` or `ToolError` the double returned, boxed so the
58 /// typed cause stays reachable via [`std::error::Error::source`].
59 #[source]
60 source: Box<dyn std::error::Error + Send + Sync>,
61 },
62
63 /// Compaction policy failed (e.g. LLM summariser returned non-text).
64 #[error("runlog compaction error: {0}")]
65 Compaction(String),
66
67 /// A capture-persistence backend operation (`KvStore` put/get/keys/delete)
68 /// failed. Carries the backend error as a typed source.
69 #[error("capture persistence backend error")]
70 CaptureBackend {
71 /// Downcast to `klieo_core::BusError` to branch on the backend failure
72 /// kind (unsupported, conflict, transport).
73 #[source]
74 source: Box<dyn std::error::Error + Send + Sync>,
75 },
76
77 /// A capture blob failed to serialize on persist or deserialize on load
78 /// (e.g. a corrupt or truncated stored value).
79 #[error("capture codec error")]
80 CaptureCodec {
81 /// Downcast to `serde_json::Error` for the byte offset of the
82 /// malformed blob.
83 #[source]
84 source: Box<dyn std::error::Error + Send + Sync>,
85 },
86}