This document explains the migration from storing absolute file paths to relative file paths in the database.
The File table in the database now stores paths relative to NEXT_PUBLIC_MUSIC_LIBRARY_FOLDER instead of absolute paths. This makes the database more portable and allows the music library folder to be relocated without database changes.
Before running the migration, create a full backup of your database.
Edit prisma/migrations/convert_file_paths_to_relative.sql:
- Replace
/Users/Flo/Music/Emptywith your actualNEXT_PUBLIC_MUSIC_LIBRARY_FOLDERpath - Make sure to expand the
$HOMEvariable to the full path (e.g.,/Users/YourName/Music/Empty)
# Using psql (PostgreSQL)
psql -d databasename -f prisma/migrations/convert_file_paths_to_relative.sql
# Review the output to ensure all paths were converted successfully
# If everything looks good, run:
# COMMIT;
# If there are issues:
# ROLLBACK;The migration script:
- Validates that all existing paths start with your music library folder
- Converts absolute paths to relative paths
- Verifies the conversion was successful
- Keeps the transaction open by default for safety
If your files have been moved to a different filesystem or drive (which would change their inode numbers), run the inode migration:
# First, do a dry run to see what would change
node prisma/migrations/update_file_inodes.js --dry-run
# If everything looks good, run the actual migration
node prisma/migrations/update_file_inodes.jsThis step is only necessary if:
- Files were moved to a different filesystem/drive
- The filesystem was reformatted
- Database was restored on a different system
- You're experiencing inode-related duplicate detection issues
After successfully running the migration(s), deploy the updated code. The code changes include:
- Database writes: All file paths are now stored as relative paths
- Database reads: Paths are joined with
NEXT_PUBLIC_MUSIC_LIBRARY_FOLDERfor filesystem operations - File watcher: Converts chokidar's absolute paths to relative before database queries
- Upload handler: Converts paths to relative for database queries
File.pathnow contains relative paths (e.g.,Artist/Album/01 Track.mp3)- Previously contained absolute paths (e.g.,
/Users/Flo/Music/Empty/Artist/Album/01 Track.mp3)
-
src/server/db/createTrack.ts
- Stores
relativePathinstead of absolutepathin database - Joins with library folder when checking existing file paths
- Stores
-
src/server/persistent/watcher.ts
- Converts chokidar's absolute paths to relative for all database queries
- File add, unlink, and move operations all use relative paths
-
src/pages/api/file/[id].ts
- Joins
NEXT_PUBLIC_MUSIC_LIBRARY_FOLDERwithfile.pathfor filesystem operations - Logging now uses relative path directly (already relative in DB)
- Joins
-
src/server/trpc/router/edit/track.ts
- Joins path with library folder for
parseFile()andacoustId.identify() - Unlink operations use joined absolute path
- Joins path with library folder for
-
src/server/trpc/router/edit/artist.ts & album.ts
- Delete operations join path with library folder before unlinking files
-
src/pages/api/cold-start.tsx
- Validation compares joined absolute paths with filesystem scan results
-
src/pages/api/upload/index.tsx
- Converts proposed path to relative before querying database
After migration and deployment, verify:
- File playback works: Try playing tracks from different albums
- File upload works: Upload a new track
- File deletion works: Delete a test track
- Watcher works: Add/remove a file directly in the music folder
- Check logs: Ensure no "file not found" errors
If issues occur, you can rollback:
- Database: Restore from backup taken in step 1
- Code: Revert to the previous commit
- Portability: Database can be moved between systems with different music library locations
- Flexibility: Music library folder can be relocated without database migration
- Consistency: Matches the pattern already used by the
Imagetable - Cleaner logs: File paths in logs are now relative and easier to read
- The
Imagetable already used relative paths, so it didn't need migration - All filesystem operations (
readFile,createReadStream,parseFile,unlink, etc.) now join the relative path withNEXT_PUBLIC_MUSIC_LIBRARY_FOLDER - Database queries use relative paths for lookups
- External libraries (like
acoustId.identify) receive absolute paths (joined before calling)