Add schema compatibility probe to prevent silent migration failures (bd-ckvw)
- Implement comprehensive schema probe in sqlite.New() that verifies all expected tables and columns after migrations - Add retry logic: if probe fails, retry migrations once - Return clear fatal error with missing schema elements if probe still fails - Enhance daemon version gating: refuse RPC if client has newer minor version - Improve checkVersionMismatch messaging: verify schema before claiming upgrade - Add schema compatibility check to bd doctor command - Add comprehensive tests for schema probing This prevents the silent migration failure bug where: 1. Migrations fail silently 2. Database queries fail with 'no such column' errors 3. Import logic misinterprets as 'not found' and tries INSERT 4. Results in cryptic UNIQUE constraint errors Fixes #262 Amp-Thread-ID: https://ampcode.com/threads/T-0d7ae2c0-9f12-4f9b-85d1-1291488af150 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -56,11 +56,23 @@ func (s *Server) checkVersionCompatibility(clientVersion string) error {
|
||||
clientVersion, ServerVersion)
|
||||
}
|
||||
|
||||
// Compare full versions - daemon should be >= client for backward compatibility
|
||||
// Compare full versions - daemon must be >= client (bd-ckvw: strict minor version gating)
|
||||
// This prevents stale daemons from serving requests with old schema assumptions
|
||||
cmp := semver.Compare(serverVer, clientVer)
|
||||
if cmp < 0 {
|
||||
// Server is older than client within same major version - may be missing features
|
||||
return fmt.Errorf("version mismatch: daemon %s is older than client %s. Upgrade and restart daemon: 'bd daemon --stop && bd daemon'",
|
||||
// Server is older than client - refuse connection
|
||||
// Extract minor versions for clearer error message
|
||||
serverMinor := semver.MajorMinor(serverVer)
|
||||
clientMinor := semver.MajorMinor(clientVer)
|
||||
|
||||
if serverMinor != clientMinor {
|
||||
// Minor version mismatch - schema may be incompatible
|
||||
return fmt.Errorf("version mismatch: client v%s requires daemon upgrade (daemon is v%s). The client may expect schema changes not present in this daemon version. Run: bd daemons killall",
|
||||
clientVersion, ServerVersion)
|
||||
}
|
||||
|
||||
// Patch version difference - usually safe but warn
|
||||
return fmt.Errorf("version mismatch: daemon v%s is older than client v%s. Upgrade and restart daemon: bd daemons killall",
|
||||
ServerVersion, clientVersion)
|
||||
}
|
||||
|
||||
|
||||
@@ -323,7 +323,7 @@ func TestVersionCheckMessage(t *testing.T) {
|
||||
serverVersion: testVersion100,
|
||||
clientVersion: "1.1.0",
|
||||
expectError: true,
|
||||
errorContains: "daemon 1.0.0 is older than client 1.1.0",
|
||||
errorContains: "client v1.1.0 requires daemon upgrade",
|
||||
},
|
||||
{
|
||||
name: "Compatible versions",
|
||||
|
||||
Reference in New Issue
Block a user