JuliusBrussee/caveman · error

native session usage: %w

Error message

native session usage: %w

What it means

Returned by Store.SessionUsage when the aggregate SELECT over the requests table for the given session fails at the database layer. Identity already validated, so causes are environmental: the DB is closed, the requests table is missing/corrupt, or the query hits an I/O error (bad disk, moved file).

Source

Thrown at proxy/internal/store/store.go:646

		`SELECT COUNT(*),
		        COALESCE(SUM(CASE WHEN token_usage_basis = 'provider_complete' THEN 1 ELSE 0 END),0),
		        COALESCE(SUM(input_tokens),0), COALESCE(SUM(output_tokens),0),
		        COALESCE(SUM(cached_input_tokens),0), COALESCE(SUM(cache_creation_input_tokens),0),
		        COALESCE(SUM(reasoning_tokens),0), COALESCE(SUM(total_cost_usd),0),
		        COALESCE(SUM(savings_usd),0), COALESCE(SUM(compression_tokens_before),0),
		        COALESCE(SUM(compression_tokens_after),0),
		        COALESCE(GROUP_CONCAT(DISTINCT NULLIF(compression_token_count_basis,'')),''),
		        COALESCE(GROUP_CONCAT(DISTINCT NULLIF(session_correlation_basis,'')),'')
		   FROM requests WHERE session_id = ?`,
		sessionID,
	).Scan(
		&out.Requests, &out.ProviderCompleteRequests, &out.InputTokens, &out.OutputTokens,
		&out.CachedInputTokens, &out.CacheCreationInputTokens, &out.ReasoningTokens,
		&out.CatalogListPriceSubtotalUSD, &out.InferredSavingsUSD,
		&out.CompressionTokensBefore, &out.CompressionTokensAfter, &compressionBases, &correlationBases,
	)
	if err != nil {
		return out, fmt.Errorf("native session usage: %w", err)
	}
	if out.Requests == 0 {
		return out, nil
	}
	out.Status = "correlated"
	if !strings.Contains(correlationBases, ",") {
		out.CorrelationBasis = correlationBases
	} else {
		out.CorrelationBasis = "mixed"
	}
	if out.ProviderCompleteRequests == out.Requests {
		out.TokenUsageCoverage = "provider_complete"
	} else {
		out.TokenUsageCoverage = "mixed_or_unavailable"
	}
	if compressionBases == "estimated_engine_o200k" || compressionBases == "legacy_unspecified" {
		out.CompressionTokenCountBasis = compressionBases
	} else if compressionBases != "" {

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Ensure the store is still open — do not share a Store across goroutines after Close; open per command if needed
  2. If the table is missing, the DB came from a foreign/older schema: recreate with store.Open on a fresh path or re-run migrations
  3. Run sqlite3 <db> 'PRAGMA integrity_check' to detect corruption; .recover or delete and rebuild if it fails
  4. Read from a stable copy: stop the proxy, copy the file, query the copy

Example fix

# before: stats command against a mid-backup file
$ cp ~/.caveman/caveman.db /tmp/db.bak & caveman-proxy stats --db /tmp/db.bak
native session usage: disk I/O error

# after: quiesce first, then copy, then query
$ caveman-proxy stop 2>/dev/null || true
$ cp ~/.caveman/caveman.db /tmp/db.bak
$ caveman-proxy stats --db /tmp/db.bak
Defensive patterns

Strategy: try-catch

Validate before calling

// Cheap liveness probe before the aggregate
var one int
if err := st.DB().QueryRow("SELECT 1 FROM requests LIMIT 1").Scan(&one); err != nil && err != sql.ErrNoRows {
    return fmt.Errorf("requests table unavailable: %w", err)
}

Try / catch

snap, err := st.SessionUsage(id)
if err != nil {
    if errors.Is(err, sql.ErrConnDone) || strings.Contains(err.Error(), "database is closed") {
        // lifecycle bug in caller: re-open the store and retry once
    }
    if strings.Contains(err.Error(), "no such table") {
        // foreign schema: recreate or point at the right DB
    }
    return err
}

Prevention

When it happens

Trigger: Calling SessionUsage on a Store whose Close() already ran (sql: database is closed), against a DB where the requests table was dropped/renamed by a migration mismatch, or while the file is corrupt/being restored from backup.

Common situations: Querying usage during shutdown races; a stats command pointed at a caveman.db created by an incompatible version; the DB file on a flaky mount returning I/O errors during the scan; reading a partially-copied backup file.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/2f6b4a8ec769b034. Report an issue: GitHub.