Skip to main content

Common Issues

Symptoms:
  • Fold states appear on Device A but not Device B
  • Folds reset to unfolded state after switching devices
  • Inconsistent fold behavior across vault instances
Possible Causes:
  1. Sync disabled in plugin settings
  2. File sync solution not syncing data.json
  3. Plugin not enabled on all devices
  4. Cached fold states out of sync
Solutions:Check Plugin Status:
1. Go to Settings → Community plugins
2. Verify "Sync Folds" is enabled
3. Check that the toggle switch is ON (not grayed out)
Verify Sync Settings:
1. Open command palette (Ctrl/Cmd + P)
2. Search for "Sync Folds: Export folds from local storage"
3. Run the command
4. Wait for file sync to complete
5. On Device B, run "Sync Folds: Import folds into local storage"
Check File Sync Configuration:Ensure your file sync solution (Obsidian Sync, iCloud, Syncthing, Git, etc.) is configured to sync:
.obsidian/plugins/sync-folds/data.json
For Obsidian Sync:
  • Settings → Sync → Settings sync → Enable “Community plugins”
For iCloud/Dropbox/OneDrive:
  • Verify the .obsidian/plugins/ folder is not excluded
  • Check that hidden files are being synced
For Git:
  • Add to .gitignore if present:
    # DO NOT ignore sync-folds data
    !.obsidian/plugins/sync-folds/data.json
    
Force a Fresh Sync:
  1. On Device A (source of truth):
    • Run “Export folds from local storage” command
    • Wait for file sync to upload data.json
  2. On Device B:
    • Close all notes
    • Run “Import folds into local storage” command
    • Reopen notes to see folds applied
Symptoms:
  • Plugin appears in Community plugins list but doesn’t load
  • “Sync Folds” commands don’t appear in command palette
  • Console shows plugin errors
Possible Causes:
  1. Corrupted installation
  2. Missing or invalid manifest.json
  3. Incompatible Obsidian version
  4. JavaScript errors during initialization
Solutions:Verify Installation:
Check that these files exist:
.obsidian/plugins/sync-folds/main.js
.obsidian/plugins/sync-folds/manifest.json
Check Obsidian Version:The plugin requires Obsidian v0.15.0 or later.
  • Go to Settings → About
  • Check “Current version”
  • Update Obsidian if necessary
Reinstall Plugin:
  1. Settings → Community plugins
  2. Click the “X” next to “Sync Folds” to uninstall
  3. Browse community plugins
  4. Search for “Sync Folds” and reinstall
  5. Enable the plugin
Check Developer Console:
  1. Open developer console (Ctrl/Cmd + Shift + I)
  2. Look for errors related to “sync-folds” or “[SyncFolds]”
  3. Common errors:
    • Failed to load plugin sync-folds: Missing or corrupted main.js
    • TypeError: Cannot read property 'appId' of undefined: Obsidian API incompatibility
Manual Installation (Advanced):If automatic installation fails:
  1. Download the latest release from GitHub
  2. Extract main.js and manifest.json
  3. Copy to .obsidian/plugins/sync-folds/
  4. Restart Obsidian
  5. Enable plugin in Settings
Symptoms:
  • Folds appear in random files
  • Folds don’t match document structure
  • Console shows JSON parsing errors
  • Plugin stops responding after a while
Possible Causes:
  1. Multiple Obsidian instances writing to same vault
  2. Browser extensions interfering with localStorage
  3. Corrupted fold data in data.json
  4. Manual edits to data.json with invalid JSON
Solutions:Clear localStorage (Nuclear Option):
This will remove ALL fold states for the current vault. Export first if you want to preserve them.
  1. Open developer console (Ctrl/Cmd + Shift + I)
  2. Go to “Application” or “Storage” tab
  3. Expand “Local Storage”
  4. Find entries matching {appId}-note-fold-*
  5. Delete all fold-related entries
  6. Run “Export folds from local storage” to regenerate
Reset Plugin Data:
  1. Disable “Sync Folds” plugin
  2. Close Obsidian
  3. Delete .obsidian/plugins/sync-folds/data.json
  4. Reopen Obsidian
  5. Enable “Sync Folds” plugin
  6. Plugin will create fresh data.json from current localStorage
Validate data.json Format:The data.json file should look like:
{
  "enableSync": true,
  "folds": "{\"path/to/file.md\":{\"folds\":[{\"from\":5,\"to\":12}],\"lines\":100}}"
}
Note: folds is a JSON string containing escaped quotes.Check for Multiple Obsidian Instances:Running multiple Obsidian windows/instances for the same vault can cause conflicts:
  1. Close all Obsidian windows
  2. Reopen only one instance
  3. Verify folds are working
  4. If using multiple devices, ensure they’re not open simultaneously
Symptoms:
  • data.json keeps getting overwritten
  • Fold states alternate between two different sets
  • “Conflicted copy” files appear in sync folder
  • Folds disappear randomly
Possible Causes:
  1. Both devices writing to data.json simultaneously
  2. File sync service creating conflict copies
  3. Network latency causing delayed syncs
  4. Plugin’s debouncing not sufficient for sync solution
Solutions:For Obsidian Sync:Obsidian Sync handles conflicts automatically. If issues persist:
  1. Settings → Sync → Vault size over limit
    • Check if you’re near the limit (may cause partial syncs)
  2. Settings → Sync → Sync activity
    • Look for “Failed to upload” or “Conflict” messages
  3. Temporarily disable sync, export folds, re-enable sync
For iCloud/Dropbox/OneDrive:These services may create “conflicted copy” files:
  1. Search for files named like:
    data (conflicted copy 2024-03-15).json
    data (Jane's MacBook Pro's conflicted copy).json
    
  2. Manually merge the data:
    • Open both files
    • Copy fold entries from conflicted copy
    • Paste into main data.json (ensure valid JSON)
    • Delete conflicted copy
  3. Run “Import folds into local storage”
For Git:Git may create merge conflicts in data.json:
  1. If merge conflict occurs:
    git status  # Shows data.json as conflicted
    
  2. Decide which version to keep (usually the most recent)
  3. Resolve manually or choose one side:
    git checkout --theirs .obsidian/plugins/sync-folds/data.json
    git add .obsidian/plugins/sync-folds/data.json
    git commit
    
  4. Or use a merge tool to combine both versions
For Syncthing:Syncthing may create .sync-conflict files:
  1. Look for:
    data.json.sync-conflict-20240315-120000
    
  2. Compare with main data.json
  3. Merge fold data manually
  4. Delete conflict file
Best Practices to Avoid Conflicts:
  • Close Obsidian on Device A before opening on Device B
  • Run “Export folds” before closing Obsidian
  • Wait for file sync to complete before switching devices
  • Use a sync solution with built-in conflict resolution (Obsidian Sync recommended)
Symptoms:
  • Noticeable delay when folding/unfolding sections
  • Obsidian freezes briefly during fold operations
  • High CPU usage when working with large documents
  • Slow file switching
Possible Causes:
  1. Very large vault with thousands of files
  2. Large data.json file (> 1MB)
  3. Slow disk I/O
  4. Debouncing delay too short, causing excessive writes
Solutions:Check data.json Size:
# On macOS/Linux
ls -lh .obsidian/plugins/sync-folds/data.json

# On Windows PowerShell
Get-Item .obsidian/plugins/sync-folds/data.json | Select-Object Length
If data.json is > 1MB:
  1. Many folds are being tracked
  2. Consider pruning old/unused fold states:
    • Open developer console
    • Run:
      const plugin = app.plugins.getPlugin('sync-folds')
      const folds = JSON.parse(plugin.settings.folds)
      console.log('Total files with folds:', Object.keys(folds).length)
      console.log('Files:', Object.keys(folds))
      
  3. Manually edit data.json to remove folds for deleted files
Optimize for Large Vaults:If you have > 10,000 files:
  • Consider disabling sync temporarily when doing bulk operations
  • Fold only actively used documents
  • Unfold all before archiving notes
Disable Sync During Heavy Work:
1. Run command: "Export folds from local storage" (backup current state)
2. Disable plugin temporarily
3. Perform heavy editing/refactoring
4. Re-enable plugin
5. Run command: "Import folds into local storage" (restore folds)
Check Disk Performance:If your vault is on a network drive or slow external disk:
  • Move vault to local SSD for better performance
  • Ensure file sync service isn’t saturating disk I/O
  • Check for antivirus software scanning every file write

Debugging Steps

Step 1: Verify Plugin is Enabled

  1. Open Settings → Community plugins
  2. Find “Sync Folds” in the installed plugins list
  3. Ensure the toggle is ON (blue/green, not grayed out)
  4. If OFF, toggle it ON and check if commands appear

Step 2: Check data.json Exists

Navigate to your vault’s plugin folder:
<Vault>/.obsidian/plugins/sync-folds/data.json
The file should contain:
{
  "enableSync": true,
  "folds": "{...}"
}
If the file doesn’t exist or is empty:
  1. Enable the plugin (it will create the file)
  2. Run “Export folds from local storage” command

Step 3: Inspect localStorage

Open the developer console (Ctrl/Cmd + Shift + I) and run:
// Get the current vault's app ID
const appId = app.appId
console.log('App ID:', appId)

// Find all fold-related keys
const foldKeys = []
for (let i = 0; i < localStorage.length; i++) {
    const key = localStorage.key(i)
    if (key.startsWith(`${appId}-note-fold-`)) {
        foldKeys.push(key)
    }
}
console.log('Fold keys in localStorage:', foldKeys.length)
console.log('Sample keys:', foldKeys.slice(0, 5))
Expected output:
App ID: abc123def456
Fold keys in localStorage: 42
Sample keys: [
  "abc123def456-note-fold-Daily Notes/2024-03-15.md",
  "abc123def456-note-fold-Projects/README.md",
  ...
]
If no keys are found:
  • Fold some headings in a note
  • Run the script again to verify keys are being created

Step 4: Check Sync is Working

  1. Create a test fold:
    • Open any note
    • Fold a heading (click the arrow or use Ctrl/Cmd + Shift + [)
    • Wait 1 second (debounce delay)
  2. Verify it was saved:
    const plugin = app.plugins.getPlugin('sync-folds')
    const folds = JSON.parse(plugin.settings.folds)
    console.log('Saved folds:', folds)
    
  3. Check the file path appears:
    • Look for your test note’s path in the output
    • If missing, the plugin’s localStorage interception may not be working

Step 5: Enable Debug Logging

To see detailed plugin activity:
Debug logging requires rebuilding the plugin from source code. This is an advanced troubleshooting step.
  1. Clone the plugin repository
  2. Edit esbuild.config.mjs and change:
    define: {
        DEBUG: 'false'  // Change to 'true'
    }
    
  3. Build: npm run build
  4. Copy main.js to your vault’s plugin folder
  5. Restart Obsidian
  6. Open developer console and filter by [SyncFolds]
You’ll see detailed logs:
[SyncFolds] Plugin loaded with settings: {...}
[SyncFolds] Intercepting localStorage
[SyncFolds] Fold state changed: Daily Notes/2024-03-15.md
[SyncFolds] Debouncing file sync (150ms) for: Daily Notes/2024-03-15.md
[SyncFolds] Executing debounced file sync for: Daily Notes/2024-03-15.md
[SyncFolds] Upserting fold state for: Daily Notes/2024-03-15.md
[SyncFolds] Updated fold state for: Daily Notes/2024-03-15.md
The log() function is defined in log.ts:3-7 and only outputs when DEBUG is true.

Error Messages

”Failed to parse folds string”

Full Error:
Failed to parse folds string: SyntaxError: Unexpected token...
Cause: The folds field in data.json contains invalid JSON. Solution:
  1. Open .obsidian/plugins/sync-folds/data.json
  2. Check if the folds value is properly formatted:
    "folds": "{\"file.md\":{\"folds\":[],\"lines\":10}}"
    
  3. If corrupted, replace with "folds": "{}"
  4. Restart Obsidian
  5. Run “Export folds from local storage” to regenerate
Source Reference: main.ts:62-65

”Failed to parse fold JSON”

Full Error:
Failed to parse fold JSON: SyntaxError: Unexpected token...
Cause: A specific fold state in localStorage is corrupted. Solution:
  1. Identify the problematic file from console logs
  2. Open developer console
  3. Remove the corrupted entry:
    const appId = app.appId
    const filePath = "path/to/problematic/file.md"  // From error message
    localStorage.removeItem(`${appId}-note-fold-${filePath}`)
    
  4. Refold the document manually
Source Reference: main.ts:260

”Fold state removed”

Log Message:
[SyncFolds] Fold state removed: file.md
Cause: This is normal behavior when all folds in a file are unfolded. Context: When Obsidian unfolds the last folded section in a file, it removes the localStorage entry entirely rather than storing an empty fold list. No Action Needed: This is expected behavior. Source Reference: main.ts:155-156

Advanced Troubleshooting

Manually Inspecting Plugin State

Open the developer console and run:
const plugin = app.plugins.getPlugin('sync-folds')

// Check if plugin is loaded
if (!plugin) {
    console.error('Plugin not loaded or not installed')
} else {
    console.log('Plugin loaded successfully')
    
    // Check settings
    console.log('Enable sync:', plugin.settings.enableSync)
    
    // Count folds
    const folds = JSON.parse(plugin.settings.folds)
    console.log('Total files with folds:', Object.keys(folds).length)
    
    // Check cache
    console.log('Cache populated:', Object.keys(plugin.cachedFolds).length > 0)
    
    // Check if localStorage is intercepted
    console.log('Original setItem preserved:', plugin.originalSetItem !== undefined)
}

Comparing localStorage and data.json

To check if they’re in sync:
const plugin = app.plugins.getPlugin('sync-folds')
const appId = app.appId

// Get folds from data.json
const savedFolds = JSON.parse(plugin.settings.folds)
const savedPaths = Object.keys(savedFolds)

// Get folds from localStorage
const localFolds = []
for (let i = 0; i < localStorage.length; i++) {
    const key = localStorage.key(i)
    if (key.startsWith(`${appId}-note-fold-`)) {
        const filePath = key.replace(`${appId}-note-fold-`, '')
        localFolds.push(filePath)
    }
}

console.log('In data.json:', savedPaths.length)
console.log('In localStorage:', localFolds.length)

// Find differences
const inJsonOnly = savedPaths.filter(p => !localFolds.includes(p))
const inLocalOnly = localFolds.filter(p => !savedPaths.includes(p))

console.log('Only in data.json:', inJsonOnly)
console.log('Only in localStorage:', inLocalOnly)
If there are differences:
  • Run “Export folds from local storage” to update data.json with localStorage
  • Or run “Import folds into local storage” to update localStorage with data.json

Testing localStorage Interception

Verify the plugin is intercepting localStorage:
const appId = app.appId
const testKey = `${appId}-note-fold-test-file.md`
const testValue = JSON.stringify({
    folds: [{ from: 0, to: 5 }],
    lines: 10
})

// This should trigger the plugin's intercepted setItem
localStorage.setItem(testKey, testValue)

// Wait 200ms for debounce
setTimeout(() => {
    const plugin = app.plugins.getPlugin('sync-folds')
    const folds = JSON.parse(plugin.settings.folds)
    
    if (folds['test-file.md']) {
        console.log('✅ Interception working! Test fold was saved.')
    } else {
        console.error('❌ Interception NOT working. Test fold was not saved.')
    }
    
    // Cleanup
    localStorage.removeItem(testKey)
}, 200)

Getting Help

If you’ve tried all troubleshooting steps and still have issues:
  1. Check GitHub Issues:
  2. Create a Bug Report:
    • Include:
      • Obsidian version (Settings → About)
      • Plugin version (Settings → Community plugins)
      • Operating system
      • File sync solution (Obsidian Sync, iCloud, etc.)
      • Error messages from console
      • Steps to reproduce
  3. Gather Debug Information:
    // Run this in the console and include output in bug report
    const plugin = app.plugins.getPlugin('sync-folds')
    console.log('Obsidian version:', app.vault.adapter.basePath)
    console.log('Plugin settings:', plugin?.settings)
    console.log('Folds count:', Object.keys(JSON.parse(plugin?.settings?.folds || '{}')).length)
    console.log('localStorage entries:', (() => {
        const appId = app.appId
        let count = 0
        for (let i = 0; i < localStorage.length; i++) {
            if (localStorage.key(i).startsWith(`${appId}-note-fold-`)) count++
        }
        return count
    })())
    
Do not share your entire data.json file publicly as it contains file paths from your vault, which may reveal personal information.

Build docs developers (and LLMs) love