{"record":{"id":"535f5a83c98778ee","repo":"benbjohnson/litestream","slug":"meta-path-collision-databases-s-and-s-would-sha","errorCode":null,"errorMessage":"meta-path collision: databases %s and %s would share meta-path %s, causing replication state corruption","messagePattern":"meta-path collision: databases (.+?) and (.+?) would share meta-path (.+?), causing replication state corruption","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"cmd/litestream/main.go","lineNumber":855,"sourceCode":"\n\tif len(dbPaths) == 0 && !dbc.Watch {\n\t\treturn nil, fmt.Errorf(\"no SQLite databases found in directory %s with pattern %s\", dirPath, dbc.Pattern)\n\t}\n\n\t// Create DB instances for each found database\n\tvar dbs []*litestream.DB\n\tmetaPaths := make(map[string]string)\n\n\tfor _, dbPath := range dbPaths {\n\t\tdb, err := newDBFromDirectoryEntry(dbc, dirPath, dbPath)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to create DB for %s: %w\", dbPath, err)\n\t\t}\n\n\t\t// Validate unique meta-path to prevent replication state corruption\n\t\tif mp := db.MetaPath(); mp != \"\" {\n\t\t\tif existingDB, exists := metaPaths[mp]; exists {\n\t\t\t\treturn nil, fmt.Errorf(\"meta-path collision: databases %s and %s would share meta-path %s, causing replication state corruption\", existingDB, dbPath, mp)\n\t\t\t}\n\t\t\tmetaPaths[mp] = dbPath\n\t\t}\n\n\t\tdbs = append(dbs, db)\n\t}\n\n\treturn dbs, nil\n}\n\n// newDBFromDirectoryEntry creates a DB instance for a database discovered via directory replication.\nfunc newDBFromDirectoryEntry(dbc *DBConfig, dirPath, dbPath string) (*litestream.DB, error) {\n\t// Calculate relative path from directory root\n\trelPath, err := filepath.Rel(dirPath, dbPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to calculate relative path for %s: %w\", dbPath, err)\n\t}\n","sourceCodeStart":837,"sourceCodeEnd":873,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/cmd/litestream/main.go#L837-L873","documentation":"Litestream computes a metadata path for every database discovered via directory replication. If two databases would resolve to the same meta-path, both would read/write the same replication state and corrupt each other's checkpoints. The function detects this during setup and aborts, naming both colliding databases and the shared path.","triggerScenarios":"In the per-DB loop, db.MetaPath() returns a value already present in the metaPaths map — e.g. two distinct database files whose relative paths collapse to the same meta path (symlinks to the same file, case-insensitive filesystem collisions, or a custom meta-path template that doesn't vary per relative path).","commonSituations":"Using meta-path with a template that omits the per-DB component; symlinked duplicates in the scanned directory; a filesystem where two filenames differ only in case but the meta store is case-insensitive.","solutions":["Use meta-dir instead of meta-path — it derives a unique per-database path from the relative path automatically.","Remove duplicate/symlinked files so each discovered database has a distinct relative path.","If using a custom meta-path derivation, ensure it incorporates the per-database relative path.","Restore only one of the colliding databases from backup instead of both."],"exampleFix":"# before\n- dir: /data\n  pattern: \"*.db\"\n  meta-path: /var/lib/litestream/meta   # same for every db -> collision\n\n# after\n- dir: /data\n  pattern: \"*.db\"\n  meta-dir: /var/lib/litestream/meta    # per-db: <meta-dir>/<rel-path>.litestream","handlingStrategy":"validation","validationCode":"seen := map[string]string{}\nfor _, p := range dbPaths {\n    rel, _ := filepath.Rel(dirPath, p)\n    mp := filepath.Join(metaDir, rel+\".litestream\")\n    if prev, ok := seen[mp]; ok {\n        return fmt.Errorf(\"%s and %s collide on meta-path %s\", prev, p, mp)\n    }\n    seen[mp] = p\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer meta-dir over meta-path in directory replication configs.","Don't symlink duplicate databases into the watched directory.","Ensure each database has a unique relative path (no case-only differences on case-insensitive filesystems)."],"tags":["litestream","directory-replication","state-corruption","collision"],"backgroundTag":"internal-invariant-violation","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}