How to Debug Parent Selection Issues¶
This guide helps you troubleshoot and debug parent selection problems when stacking photos.
Understanding Parent Selection¶
Parent selection determines which asset becomes the visible representative of a stack. The selection follows a strict precedence order:
- PARENT_FILENAME_PROMOTE list order (left to right)
- PARENT_EXT_PROMOTE list order (left to right)
- Built-in extension rank (
.jpeg>.jpg>.png> others) - Alphabetical order (case-insensitive)
- Local date/time (earliest first)
- Asset ID (lexicographic order)
Common Parent Selection Problems¶
Problem 1: Wrong File is Stack Parent¶
Symptom: Expected file is not the stack parent
Debug Steps:
- Enable debug logging:
LOG_LEVEL=debug
DRY_RUN=true
- Check your promotion rules:
PARENT_FILENAME_PROMOTE=edit,raw,original
PARENT_EXT_PROMOTE=.jpg,.dng
- Review the logs for parent selection details:
level=debug msg="Parent candidate" filename=IMG_1234_edited.jpg rank=1
level=debug msg="Parent candidate" filename=IMG_1234.jpg rank=2
Solutions:
- Verify promotion strings are case-insensitive but must be substrings of the filename
- Check that promoted files actually exist in the stack
- Review precedence order (filename promotion beats extension promotion)
Problem 2: Parent Changes Between Runs¶
Symptom: Different file becomes parent on each run
Causes:
- Non-deterministic file ordering (this should not happen after recent fixes)
- Changing promotion rules
- Assets with identical ranks using tie-breaking rules
Debug Steps:
- Lock down your configuration:
PARENT_FILENAME_PROMOTE=edit,raw
PARENT_EXT_PROMOTE=.jpg,.dng
- Run with same configuration multiple times:
DRY_RUN=true
LOG_LEVEL=debug
- Compare parent selections across runs
Solutions:
- Ensure consistent promotion rules
- Use more specific promotion substrings
- Add extension promotion for additional tie-breaking
Problem 3: Sequence Not Ordering Correctly¶
Symptom: Burst photos in wrong order (e.g., 0001, 0003, 0002)
Debug Steps:
- Check your sequence configuration:
# Wrong: Using generic substrings
PARENT_FILENAME_PROMOTE=0001,0002,0003
# Right: Using sequence keyword
PARENT_FILENAME_PROMOTE=sequence
- Verify sequence detection:
LOG_LEVEL=debug
DRY_RUN=true
Solutions:
- Use
sequencekeyword instead of comma-separated numbers - For specific patterns, use
sequence:4(4-digit numbers) orsequence:IMG_(with prefix) - Avoid numeric substrings that match timestamps
Problem 4: Edited Files Not Promoted¶
Symptom: RAW or original files become parents instead of edited versions
Debug Steps:
- Verify your promotion configuration:
PARENT_FILENAME_PROMOTE=edit,edited,final
PARENT_EXT_PROMOTE=.jpg,.jpeg
- Check filename patterns in logs:
LOG_LEVEL=debug
- Verify edited files actually contain the promotion substring:
IMG_1234.jpg # Does NOT contain "edit"
IMG_1234_edit.jpg # Contains "edit" ✓
IMG_1234edited.jpg # Contains "edit" ✓
Solutions:
- Use multiple promotion strings:
edit,edited,_edit,final - Add extension promotion:
.jpg,.jpegto prefer JPEGs - Use empty string for negative matching to promote files WITHOUT certain strings
Advanced Debugging Techniques¶
Technique 1: Isolate a Specific Stack¶
Test parent selection for a specific group of files:
- Create minimal test criteria:
CRITERIA='[{"key":"originalFileName","regex":{"key":"^IMG_1234","index":0}}]'
DRY_RUN=true
LOG_LEVEL=debug
- Review detailed logs for only this file group
Technique 2: Test Promotion Rules¶
Create a test script to verify promotion logic:
#!/bin/bash
# Test different promotion configurations
declare -a configs=(
"edit,raw"
"raw,edit"
"sequence,edit"
",edit,raw" # Empty string for negative matching
)
for config in "${configs[@]}"; do
echo "Testing: PARENT_FILENAME_PROMOTE=$config"
PARENT_FILENAME_PROMOTE="$config" \
DRY_RUN=true \
LOG_LEVEL=info \
./immich-stack | grep "Parent"
echo "---"
done
Technique 3: Compare Expected vs Actual¶
- Document your expected parent for each stack:
Expected: IMG_1234_edited.jpg (rank 1: contains "edited")
Actual: IMG_1234.jpg (rank 3: alphabetical)
- Trace through precedence rules to identify where expectations diverge
Technique 4: Use Dry-Run with Verbose Logging¶
Combine dry-run mode with debug logging to see all parent selection decisions:
DRY_RUN=true
LOG_LEVEL=debug
LOG_FORMAT=json # For easier parsing
./immich-stack > debug-output.log 2>&1
Then analyze the log:
# Find all parent selection events
grep "Parent candidate" debug-output.log
# Count parent selections by filename pattern
grep "Parent candidate" debug-output.log | awk '{print $5}' | sort | uniq -c
Testing Parent Selection Rules¶
Test Case 1: Basic Promotion¶
Setup:
Files:
- IMG_1234.jpg
- IMG_1234_edited.jpg
- IMG_1234.dng
Config:
PARENT_FILENAME_PROMOTE=edited
Expected: IMG_1234_edited.jpg is parent
Verification:
DRY_RUN=true LOG_LEVEL=debug ./immich-stack | grep "1234"
Test Case 2: Extension Precedence¶
Setup:
Files:
- IMG_5678.jpg
- IMG_5678.jpeg
- IMG_5678.png
Config:
PARENT_FILENAME_PROMOTE=""
PARENT_EXT_PROMOTE=.jpg,.jpeg
Expected: IMG_5678.jpeg is parent (built-in rank: jpeg > jpg > png)
Test Case 3: Sequence Ordering¶
Setup:
Files:
- BURST_0001.jpg
- BURST_0003.jpg
- BURST_0002.jpg
Config:
PARENT_FILENAME_PROMOTE=sequence
Expected: Order: 0001, 0002, 0003
Common Edge Cases¶
Unicode Filenames¶
# Works correctly - case-insensitive substring matching
PARENT_FILENAME_PROMOTE=編集,★favorites,café
Empty String Matching¶
# Promote files that DON'T contain "_edited" or "_crop"
PARENT_FILENAME_PROMOTE=,_edited,_crop
# Result:
# IMG_1234.jpg → Promoted (no _edited, no _crop)
# IMG_1234_edited.jpg → Not promoted (contains _edited)
Multiple Sequence Keywords¶
# Only first "sequence" is used, rest ignored
PARENT_FILENAME_PROMOTE=COVER,sequence,edited,sequence:4
# Result: COVER files first, then sequences, then "edited", then others
Troubleshooting Checklist¶
When debugging parent selection:
- [ ] Verify promotion strings are substrings (not regex patterns)
- [ ] Check case-insensitive matching is working
- [ ] Confirm promoted files actually exist in stack
- [ ] Review precedence order (filename > extension > built-in > alpha)
- [ ] Test with dry-run mode first
- [ ] Enable debug logging for detailed output
- [ ] Check for typos in promotion configuration
- [ ] Verify environment variables are loaded correctly
- [ ] Compare results across multiple runs for consistency
Best Practices¶
- Start Simple: Test with basic promotion rules first
- Use Dry-Run: Always test with
DRY_RUN=truebefore production - Enable Debug Logs: Use
LOG_LEVEL=debugfor detailed insights - Document Expected Behavior: Write down what you expect before running
- Test Incrementally: Add one promotion rule at a time
- Use Sequence Keyword: Prefer
sequenceover comma-separated numbers - Verify Configuration Loading: Check that env vars or CLI flags are applied
Getting Help¶
If you're still having parent selection issues:
- Collect debug logs with
LOG_LEVEL=debug - Document your configuration (CRITERIA, PARENT_FILENAME_PROMOTE, etc.)
- Provide example filenames and expected vs actual parents
- Include relevant log excerpts showing parent selection
- Open an issue on GitHub with this information