SOLVED (EDITED): iCloud Sync Issues & "File Not Found" on Windows - The NFD/iCloud Filename Conflict
[Report] SOLVED: iCloud Sync Issues & "File Not Found" on Windows - The NFD/iCloud Filename Conflict (Zotero 8)
1. Environment & Setup
- OS: macOS 13.7.8 (Primary) & Windows 11 Pro 25H2 (Secondary)
- Zotero Version: 8.0.3 (x64)
- Data Directory: Local (Fresh Installation)
- Attachment Storage:** iCloud Drive via ZotMoov (Shared folder: `...\iCloudDrive\Family Share\LIBRARY\ZOTERO-REEN`)
- Key Extension: ZotMoov (1.2.26)
2. The Problem: "The 8-Second Filename Mismatch"
- Symptom:** Attachments added on Mac (with long Korean titles) were synced to iCloud, but after ~8 seconds, the filenames were forcibly truncated by the iCloud server.
- Result:** Zotero's database recorded the original long filename, while the actual file on iCloud became shorter. This caused a permanent "File Not Found" error on Windows, as the database link and physical filename no longer matched.
- Specific Trigger:** This was most severe with **Korean characters (NFD encoding)** combined with symbols like commas (`,`) or colons (`:`).
3. Root Cause: iCloud Server-Side Sanitization & NFD Encoding
- NFD Multiplier:** On macOS, Korean characters are decomposed (NFD), making each character occupy ~3 bytes. A 70-character title can exceed 200+ bytes.
- Server-Side Truncation:** If the total path (Folders + Filename) exceeds iCloud's hidden byte limit, the server forcibly "sanitizes" the filename after upload.
- Variable Threshold:** The safe limit depends on your folder depth. In my case (~4 folders deep), the "Magic Number" for filename safety was **36 characters**.
4. The Definitive Solution: Pre-emptive Truncation
Step 1: Implement the "Safe Zone" Renaming Template
I modified the Zotero 8 template to strip illegal characters and truncate the filename `before` iCloud could intervene. This ensures Zotero's DB and the physical file always share the same name.
### Template Code: [OLD]
{{ firstCreator replaceFrom=", " replaceTo=" " }} - {{ year }} - {{ title replaceFrom=" : " replaceTo=" " replaceFrom=": " replaceTo=" " replaceFrom=", " replaceTo=" " truncate="36" }}
(Note: Adjust the `truncate` value (e.g., 30 or 40) based on your specific directory depth.)*
### Template Code: [NEW]
{{ firstCreator replaceFrom=",\s*" replaceTo="_" regexOpts="g" }} - {{ year }} - {{ title replaceFrom="[:|,]\s*|\s{2,}" replaceTo=" " regexOpts="g" replaceFrom="[\s,:]+$" replaceTo="" regexOpts="g" truncate="36" }}
(Note: Adjust the `truncate` value (e.g., 30 or 40) based on your specific directory depth.)*
The code has been refactored to improve logic efficiency and filename stability through the following enhancements:
- Regex Integration: Replaced multiple manual replaceFrom chains with a single Regular Expression (regexOpts="g"). This simplifies the code and catches various punctuation patterns (:, ,) and redundant spaces in one pass Zotero Naming Reference.
- Robust Delimiter Handling: Changed the creator separator from a space to an underscore (_). This prevents issues in command-line environments where spaces can break file paths File Naming Best Practices.
- Whitespace Optimization: Added logic (\s{2,}) to automatically collapse multiple consecutive spaces into a single space, ensuring clean and consistent formatting even with messy metadata Regex101 Tester.
The previous logic failed to prevent trailing commas because Zotero applies truncate as the final step, often re-inserting symbols at the cut boundary. To address this permanently, I integrated a boundary-anchor regex ([\s,:]+$) that specifically targets and removes punctuation and whitespace at the end of the string. This ensures that even if the title is long, the final output remains clean without relying on manual length adjustments.
Step 2: Force Rename via Zotero 8 UI
Instead of relying on auto-sync, I used the **dedicated "Rename from Parent Metadata" button in the right-side Item Pane**. This forces the database to record the sanitized, short filename immediately.
5. Final Recommendations for Non-English Users
1. Sanitize Everything: Strictly avoid commas, colons, and equals signs in templates.
2. Find Your Magic Number: If your filename changes ~8 seconds after upload, your `truncate` value is too high. Decrease it until the name remains stable.
3. Keep Paths Shallow: Deeper folder structures (Family Share, etc.) require even shorter filenames to stay within the total path limit.
4. Zotero 8 Workflow: The new Item Pane buttons are more reliable for ensuring metadata-to-file consistency than legacy context menus.
---
Shared to assist the Zotero community in optimizing cross-platform workflows with multi-byte characters and cloud sync.
1. Environment & Setup
- OS: macOS 13.7.8 (Primary) & Windows 11 Pro 25H2 (Secondary)
- Zotero Version: 8.0.3 (x64)
- Data Directory: Local (Fresh Installation)
- Attachment Storage:** iCloud Drive via ZotMoov (Shared folder: `...\iCloudDrive\Family Share\LIBRARY\ZOTERO-REEN`)
- Key Extension: ZotMoov (1.2.26)
2. The Problem: "The 8-Second Filename Mismatch"
- Symptom:** Attachments added on Mac (with long Korean titles) were synced to iCloud, but after ~8 seconds, the filenames were forcibly truncated by the iCloud server.
- Result:** Zotero's database recorded the original long filename, while the actual file on iCloud became shorter. This caused a permanent "File Not Found" error on Windows, as the database link and physical filename no longer matched.
- Specific Trigger:** This was most severe with **Korean characters (NFD encoding)** combined with symbols like commas (`,`) or colons (`:`).
3. Root Cause: iCloud Server-Side Sanitization & NFD Encoding
- NFD Multiplier:** On macOS, Korean characters are decomposed (NFD), making each character occupy ~3 bytes. A 70-character title can exceed 200+ bytes.
- Server-Side Truncation:** If the total path (Folders + Filename) exceeds iCloud's hidden byte limit, the server forcibly "sanitizes" the filename after upload.
- Variable Threshold:** The safe limit depends on your folder depth. In my case (~4 folders deep), the "Magic Number" for filename safety was **36 characters**.
4. The Definitive Solution: Pre-emptive Truncation
Step 1: Implement the "Safe Zone" Renaming Template
I modified the Zotero 8 template to strip illegal characters and truncate the filename `before` iCloud could intervene. This ensures Zotero's DB and the physical file always share the same name.
### Template Code: [OLD]
{{ firstCreator replaceFrom=", " replaceTo=" " }} - {{ year }} - {{ title replaceFrom=" : " replaceTo=" " replaceFrom=": " replaceTo=" " replaceFrom=", " replaceTo=" " truncate="36" }}
(Note: Adjust the `truncate` value (e.g., 30 or 40) based on your specific directory depth.)*
### Template Code: [NEW]
{{ firstCreator replaceFrom=",\s*" replaceTo="_" regexOpts="g" }} - {{ year }} - {{ title replaceFrom="[:|,]\s*|\s{2,}" replaceTo=" " regexOpts="g" replaceFrom="[\s,:]+$" replaceTo="" regexOpts="g" truncate="36" }}
(Note: Adjust the `truncate` value (e.g., 30 or 40) based on your specific directory depth.)*
The code has been refactored to improve logic efficiency and filename stability through the following enhancements:
- Regex Integration: Replaced multiple manual replaceFrom chains with a single Regular Expression (regexOpts="g"). This simplifies the code and catches various punctuation patterns (:, ,) and redundant spaces in one pass Zotero Naming Reference.
- Robust Delimiter Handling: Changed the creator separator from a space to an underscore (_). This prevents issues in command-line environments where spaces can break file paths File Naming Best Practices.
- Whitespace Optimization: Added logic (\s{2,}) to automatically collapse multiple consecutive spaces into a single space, ensuring clean and consistent formatting even with messy metadata Regex101 Tester.
The previous logic failed to prevent trailing commas because Zotero applies truncate as the final step, often re-inserting symbols at the cut boundary. To address this permanently, I integrated a boundary-anchor regex ([\s,:]+$) that specifically targets and removes punctuation and whitespace at the end of the string. This ensures that even if the title is long, the final output remains clean without relying on manual length adjustments.
Step 2: Force Rename via Zotero 8 UI
Instead of relying on auto-sync, I used the **dedicated "Rename from Parent Metadata" button in the right-side Item Pane**. This forces the database to record the sanitized, short filename immediately.
5. Final Recommendations for Non-English Users
1. Sanitize Everything: Strictly avoid commas, colons, and equals signs in templates.
2. Find Your Magic Number: If your filename changes ~8 seconds after upload, your `truncate` value is too high. Decrease it until the name remains stable.
3. Keep Paths Shallow: Deeper folder structures (Family Share, etc.) require even shorter filenames to stay within the total path limit.
4. Zotero 8 Workflow: The new Item Pane buttons are more reliable for ensuring metadata-to-file consistency than legacy context menus.
---
Shared to assist the Zotero community in optimizing cross-platform workflows with multi-byte characters and cloud sync.
Upgrade Storage