Troubleshooting
Common issues encountered during PeerTube-to-Vidra migration and how to resolve them.
Database Connection Issues
Cannot connect to PeerTube database
Symptom: API migration fails with failed to connect to source database
Causes and fixes:
-
Firewall blocking PostgreSQL port:
# Test connectivity from Vidra server
nc -zv peertube-db-host 5432
# If blocked, open the port or use an SSH tunnel
ssh -L 5433:localhost:5432 user@peertube-server &
# Then use localhost:5433 as source_db_host -
PostgreSQL not listening on external interfaces:
# On PeerTube server, check postgresql.conf
grep listen_addresses /etc/postgresql/*/main/postgresql.conf
# Should be: listen_addresses = '*' (or specific IP)
# Check pg_hba.conf allows remote connections
grep -v '^#' /etc/postgresql/*/main/pg_hba.conf
# Add: host peertube_prod peertube_readonly vidra-server-ip/32 md5 -
Wrong credentials:
# Test directly with psql
PGPASSWORD=your-password psql -h peertube-db-host -U peertube -d peertube_prod -c "SELECT 1;"
Migration job stuck in "pending" or "validating"
Symptom: Job never transitions to "running"
Fix: Check Vidra logs for connection errors:
docker compose logs vidra | grep -i migration
Cancel the stuck job and retry:
curl -X DELETE http://your-vidra-host:8080/api/v1/admin/migrations/$JOB_ID \
-H "Authorization: Bearer $ADMIN_TOKEN"
Data Migration Issues
"A migration is already in progress"
Symptom: 409 Conflict when starting a new migration
Cause: An existing migration job is in a non-terminal state (pending, running, or validating).
Fix:
# List all jobs
curl http://your-vidra-host:8080/api/v1/admin/migrations \
-H "Authorization: Bearer $ADMIN_TOKEN" | jq '.data[] | {id, status}'
# Cancel the running job
curl -X DELETE http://your-vidra-host:8080/api/v1/admin/migrations/$RUNNING_JOB_ID \
-H "Authorization: Bearer $ADMIN_TOKEN"
Users imported with wrong roles
Symptom: Regular users have admin access, or admins are regular users
Cause: PeerTube uses numeric roles (0=admin, 1=moderator, 2=user) that need mapping.
Fix (manual migration):
-- Verify role mapping
SELECT username, role FROM users WHERE role = 'admin';
-- Fix if needed
UPDATE users SET role = 'user' WHERE username = 'some-user' AND role = 'admin';
UPDATE users SET role = 'admin' WHERE username = 'real-admin';
Missing channel-to-user relationships
Symptom: Channels appear but have no owner, or videos show wrong channel
Cause: Username matching failed during import (PeerTube account.name didn't match Vidra users.username).
Fix:
-- Find orphaned channels
SELECT c.handle, c.account_id
FROM channels c
WHERE c.account_id IS NULL OR c.account_id NOT IN (SELECT id FROM users);
-- Reassign to admin or correct user
UPDATE channels SET account_id = (SELECT id FROM users WHERE username = 'admin')
WHERE account_id IS NULL;
Comment threading broken
Symptom: Reply comments appear as top-level comments instead of nested
Cause: PeerTube uses integer IDs for comment parent references; manual migration scripts need a PeerTube-ID-to-Vidra-UUID mapping table.
Fix: Use a two-pass import with a mapping table:
-- Step 1: Create a persistent mapping table (not TEMP, since you need it across sessions)
CREATE TABLE IF NOT EXISTS comment_id_map (
peertube_id INT PRIMARY KEY,
vidra_id UUID NOT NULL
);
-- Step 2: During first-pass import (top-level comments), record the mapping
-- Add a RETURNING clause or insert into the map after each batch
-- Step 3: Import reply comments and resolve parent references
INSERT INTO comments (id, video_id, user_id, parent_id, body, status, created_at, updated_at)
SELECT
gen_random_uuid(),
v.id,
u.id,
parent_map.vidra_id, -- Resolved parent UUID from mapping table
sub.text,
'active',
sub."createdAt",
sub."updatedAt"
FROM dblink('dbname=peertube_staging', '
SELECT vc.id, vc.text, vc."createdAt", vc."updatedAt",
vc."inReplyToCommentId",
vid.name AS video_title,
a.name AS author_name
FROM "videoComment" vc
JOIN video vid ON vid.id = vc."videoId"
JOIN account a ON a.id = vc."accountId"
WHERE vc."inReplyToCommentId" IS NOT NULL
AND vc."deletedAt" IS NULL
') AS sub(
pt_id int, text text, "createdAt" timestamptz, "updatedAt" timestamptz,
in_reply_to int,
video_title text, author_name text
)
JOIN videos v ON v.title = sub.video_title
JOIN users u ON u.username = sub.author_name
JOIN comment_id_map parent_map ON parent_map.peertube_id = sub.in_reply_to;
-- Step 4: Clean up
DROP TABLE comment_id_map;
Duplicate username conflicts
Symptom: Import skips users with ON CONFLICT (username) DO NOTHING
Cause: PeerTube may have usernames that conflict with already-created Vidra users (e.g., "admin").
Fix: Review skipped users:
-- Find PeerTube users not in Vidra
SELECT a.name FROM dblink('dbname=peertube_staging',
'SELECT name FROM account') AS sub(name text)
WHERE NOT EXISTS (SELECT 1 FROM users WHERE username = sub.name);
Storage Issues
Videos not playing after migration
Symptom: Video page loads but player shows an error or buffering forever
Causes:
-
Files not copied:
# Check if the file exists
ls -la /data/vidra/storage/web-videos/{video-uuid}.mp4 -
Wrong file permissions:
# Fix permissions (Vidra needs read access)
chown -R 1000:1000 /data/vidra/storage/
chmod -R 755 /data/vidra/storage/ -
Static file handler not configured:
# Verify Vidra serves static files
curl -I http://localhost:8080/static/web-videos/{video-uuid}.mp4
# Should return 200, not 404 -
Database references don't match filenames:
-- Check video file references in Vidra's DB
SELECT v.id, v.title FROM videos v
WHERE NOT EXISTS (
-- Verify the referenced file exists on disk
-- (Run this as a script, not pure SQL)
);
HLS playback broken
Symptom: Adaptive streaming doesn't work; video only plays in one quality
Fix: Verify the HLS directory structure:
# Each video UUID should have a directory with master playlist
ls /data/vidra/storage/streaming-playlists/hls/{video-uuid}/
# Should contain: master.m3u8, {resolution}.m3u8, *.mp4 segments
# Validate master playlist
cat /data/vidra/storage/streaming-playlists/hls/{video-uuid}/master.m3u8
# Should list all quality variants
Thumbnails showing as broken images
Fix:
# Check thumbnail exists
ls /data/vidra/storage/thumbnails/{video-uuid}.jpg
# If using S3, verify the object exists
aws s3 ls s3://vidra-storage/thumbnails/{video-uuid}.jpg --endpoint-url $S3_ENDPOINT
Federation Issues
Other instances can't discover the migrated instance
Symptom: WebFinger returns errors or wrong data
Fix:
# Test WebFinger locally
curl "http://localhost:8080/.well-known/webfinger?resource=acct:admin@your-domain.com"
# Verify the domain matches your public URL
# Check .env: PUBLIC_URL=https://your-domain.com
ActivityPub followers lost
Expected behavior: ActivityPub followers from other instances need to re-follow after migration. The federation protocol will automatically rediscover your instance through WebFinger.
To speed up re-federation:
- Ensure WebFinger and NodeInfo endpoints work
- Contact administrators of major federated instances
- ActivityPub followers should automatically rediscover within 24-48 hours
Performance Issues
Migration running slowly
Symptom: API migration job has been running for hours with low entity counts
Possible fixes:
-
Add indexes to PeerTube staging DB (for manual migration):
CREATE INDEX IF NOT EXISTS idx_video_channel_id ON video("channelId");
CREATE INDEX IF NOT EXISTS idx_comment_video_id ON "videoComment"("videoId"); -
Increase PostgreSQL connection limits on both databases
-
Run during off-peak hours to avoid resource contention
Vidra slow after large import
Fix: After importing large amounts of data, refresh database statistics:
-- Run ANALYZE on all imported tables
ANALYZE users;
ANALYZE channels;
ANALYZE videos;
ANALYZE comments;
ANALYZE playlists;
ANALYZE captions;
-- If needed, VACUUM to reclaim space
VACUUM ANALYZE;
Getting Help
If you encounter an issue not covered here:
- Check Vidra logs:
docker compose logs vidra - Check the migration job's error details via the API
- File an issue at github.com/yosefgamble/athena/issues with:
- PeerTube version you're migrating from
- Vidra version
- Migration method used (API or manual)
- Error messages and relevant logs
- Instance size (approximate user/video counts)