Files
DeepSeek-Reasonix/internal/session/transcript_initialization_error.go
T
SivanCola 2797455a1d Fix transcript initialization crash during migration
Problem: malformed legacy transcript baselines could crash the Desktop service while startup migration restored a nil projection.

Root cause: session runtime construction discarded NewProjection errors and continued into RestoreRuntime without a valid projection.

Fix: propagate typed initialization failures, release session ownership on every failed path, keep healthy migrations running, add content-free local diagnostics, and queue a deduplicated telemetry-gated exception for the crash dashboard.

Verification: session and transcript package suites, focused Desktop crash/migration tests, targeted race tests, crash worker tests, and worker typecheck pass.
2026-09-18 16:01:36 +08:00

54 lines
1.6 KiB
Go

package session
import (
"crypto/sha256"
"errors"
"fmt"
"log/slog"
"reasonix/internal/transcript"
)
// TranscriptInitializationError crosses service and migration boundaries
// without losing the original cause. LogValue never emits raw error text,
// session paths, provider metadata, or imported record identities.
type TranscriptInitializationError struct {
sessionID string
covered uint64
messageCount int
totalMessages int
cause error
}
func (e *TranscriptInitializationError) Error() string {
return fmt.Sprintf("session: initialize transcript for %q: %v", e.sessionID, e.cause)
}
func (e *TranscriptInitializationError) Unwrap() error { return e.cause }
// Classification returns a content-free reason suitable for aggregate crash
// diagnostics. Detailed correlation identifiers remain local-only in LogValue.
func (e *TranscriptInitializationError) Classification() string {
var baseline *transcript.BaselineError
if errors.As(e.cause, &baseline) {
return baseline.Code()
}
return "transcript_initialization_failed"
}
func (e *TranscriptInitializationError) LogValue() slog.Value {
attrs := []slog.Attr{
slog.Int("version", 1),
slog.String("code", "transcript_initialization_failed"),
slog.String("session_key", fmt.Sprintf("%x", sha256.Sum256([]byte(e.sessionID)))),
slog.Uint64("covered_sequence", e.covered),
slog.Int("baseline_message_count", e.messageCount),
slog.Int("baseline_total_message_count", e.totalMessages),
}
var baseline *transcript.BaselineError
if errors.As(e.cause, &baseline) {
attrs = append(attrs, slog.Any("baseline", baseline))
}
return slog.GroupValue(attrs...)
}