@@ -10,6 +10,8 @@ import (
1010 "time"
1111
1212 "github.com/google/uuid"
13+
14+ "github.com/docker/docker-agent/pkg/version"
1315)
1416
1517// Migration represents a database migration
@@ -42,6 +44,11 @@ func (m *MigrationManager) InitializeMigrations(ctx context.Context) error {
4244 return fmt .Errorf ("failed to create migrations table: %w" , err )
4345 }
4446
47+ // Check if the database was created by a newer version of the application
48+ if err := m .checkForUnknownMigrations (ctx ); err != nil {
49+ return err
50+ }
51+
4552 // Run all pending migrations
4653 err = m .RunPendingMigrations (ctx )
4754 if err != nil {
@@ -64,6 +71,30 @@ func (m *MigrationManager) createMigrationsTable(ctx context.Context) error {
6471 return err
6572}
6673
74+ // checkForUnknownMigrations checks if the database has migrations that this binary
75+ // doesn't know about, which indicates the database was created by a newer version.
76+ // This produces a clear error instead of cryptic SQL failures from schema mismatches.
77+ func (m * MigrationManager ) checkForUnknownMigrations (ctx context.Context ) error {
78+ known := getAllMigrations ()
79+ maxKnownID := known [len (known )- 1 ].ID
80+
81+ var maxAppliedID int
82+ err := m .db .QueryRowContext (ctx , "SELECT COALESCE(MAX(id), 0) FROM migrations" ).Scan (& maxAppliedID )
83+ if err != nil {
84+ return fmt .Errorf ("failed to check applied migrations: %w" , err )
85+ }
86+
87+ if maxAppliedID > maxKnownID {
88+ return fmt .Errorf (
89+ "%w: you are running docker-agent %s which supports migrations up to %d, " +
90+ "but the session database has migration %d from a newer version; " +
91+ "please upgrade docker-agent to the latest version" ,
92+ ErrNewerDatabase , version .Version , maxKnownID , maxAppliedID )
93+ }
94+
95+ return nil
96+ }
97+
6798// RunPendingMigrations executes all migrations that haven't been applied yet
6899func (m * MigrationManager ) RunPendingMigrations (ctx context.Context ) error {
69100 migrations := getAllMigrations ()
0 commit comments