How PhotoStructure copies your files
If you have automatic library organization enabled, PhotoStructure copies photos and videos from your source directories into your library. Your photos are irreplaceable, so PhotoStructure takes extra care to make sure copies succeed:
- Automatic strategy detection: Different filesystems have different quirks. PhotoStructure tests several copy methods and picks the one that works for your setup.
- Error handling: Common permission errors (especially on NAS devices like TrueNAS) are automatically retried with more compatible settings.
- Checksum verification: After each copy, PhotoStructure compares SHA checksums to confirm the file arrived intact.
TL;DR: The defaults work for most users. If file copies are failing or you want to understand what is happening, read on.
β What is a file copy strategy?
A “file copy strategy” is the method PhotoStructure uses to copy files. Each strategy has different trade-offs:
- Speed: Some methods are faster than others
- Atomicity: Whether a partial copy can leave a corrupt file behind
- Metadata preservation: Whether file permissions and timestamps are copied
- Compatibility: Whether the method works on all filesystems
π§ Available strategies
PhotoStructure supports six file copy strategies, controlled by the
fileCopyStrategy setting:
βοΈ auto (default)
PhotoStructure automatically tests each strategy when you open your library and selects the first one that works. This is the recommended setting for most users.
The test runs once per hour and creates small temporary files in your library’s originals directory to verify that copying and renaming work correctly.
β‘ builtin-reflink
Uses Node.js with “reflink” support (also called “copy-on-write” or “CoW”).
What’s a reflink? On modern filesystems like ZFS, btrfs, and APFS, a reflink creates an instant “copy” that doesn’t actually duplicate the data on disk. Instead, both files point to the same underlying data blocks. The filesystem only creates new blocks when one of the files is modified. This saves time and disk space.
If your filesystem doesn’t support reflinks, this strategy automatically falls back to a traditional copy with negligible overhead.
π¨ builtin
Uses Node.js without reflink support. This is essentially the same as
builtin-reflink on filesystems that don’t support copy-on-write.
π builtin-no-wip
Uses Node.js but skips the “work-in-progress” (.wip) pattern.
What’s the .wip pattern? Normally, PhotoStructure copies files to a
temporary name (like .WIP-abc123-photo.jpg) and then renames it to the final
name. This ensures that if PhotoStructure crashes mid-copy, you won’t have a
partial, corrupt file in your library.
Some filesystems (particularly certain network filesystems) have trouble with file renames. If you see errors about rename operations failing, try this strategy.
πΎ native-preserve
Uses your operating system’s native copy command (cp -a on Linux, ditto on
macOS, Copy-Item on Windows) with full metadata preservation.
What’s metadata preservation? This copies not just the file contents, but also permissions, ownership, extended attributes, and other filesystem metadata.
This strategy can fail on some NAS systems (see TrueNAS/ZFS troubleshooting below).
π¦ native
Uses the native copy command without metadata preservation (cp -f on Linux,
ditto --norsrc on macOS). This is the most compatible option but doesn’t
preserve file permissions.
π€ When to change from auto
The auto setting works well for most users. You might need to change it if:
You want to force reflinks: Set
builtin-reflinkif you know your filesystem supports copy-on-write and want to ensure reflinks are used.You’re having rename errors: Set
builtin-no-wipif file renames fail on your network filesystem.You need metadata preservation: Set
native-preserveif you specifically need file permissions copied (and your filesystem supports it).Nothing else works: Set
nativeas a last resort for maximum compatibility.
βοΈ How to change the strategy
You can set the strategy in your settings.toml file:
fileCopyStrategy = "builtin-reflink"
Or via environment variable:
PS_FILE_COPY_STRATEGY="builtin-reflink"
Valid values: auto, builtin-reflink, builtin, builtin-no-wip,
native-preserve, native
π¨ TrueNAS/ZFS permission errors
If you’re running PhotoStructure on TrueNAS (formerly FreeNAS) and file copies are failing with “permission denied” or “operation not permitted” errors, you may be hitting a ZFS ACL restriction.
β The problem
TrueNAS defaults SMB (Windows file sharing) datasets to
aclmode=restricted. This setting rejects attempts to change file permissions
on files that have non-trivial
ACLs (Access Control
Lists).
When PhotoStructure (or any application) tries to copy a file with cp -a
(which preserves permissions), ZFS rejects the permission-setting operation with
an EPERM (operation not permitted) error.
β¨ PhotoStructure’s automatic fix
When PhotoStructure detects this permission error, it automatically retries the copy without the permission-preservation flags. This means your copied files will have default permissions rather than preserving the source file’s permissions.
For most photo libraries, this is perfectly fine: you typically want all photos readable by the same user anyway.
π§ TrueNAS fix (optional)
If you want to preserve file permissions, you can change the ZFS ACL mode:
zfs set aclmode=passthrough poolname/dataset
Replace poolname/dataset with your actual pool and dataset path.
Caution: This changes how ZFS handles ACLs for the entire dataset. Review the TrueNAS documentation and understand the implications before making this change, especially on production systems.
For more details on aclmode, see this TrueNAS community
discussion.
π Strategy comparison table
| Strategy | Speed | Atomic | Reflink | Preserves metadata |
|---|---|---|---|---|
auto | Varies | Yes | Maybe | No |
builtin-reflink | Fastest* | Yes | Yes | No |
builtin | Fast | Yes | No | No |
builtin-no-wip | Fast | No | No | No |
native-preserve | Slower | Yes | No | Yes |
native | Slower | Yes | No | No |
* On copy-on-write filesystems (ZFS, btrfs, APFS); same speed as builtin on
other filesystems.
Atomic: Whether a crash during copy can leave a corrupt file. “Yes” means PhotoStructure uses a temporary file and rename, so crashes are safe.
Reflink: Whether the strategy can use copy-on-write for instant, space-saving copies.
Preserves metadata: Whether file permissions and extended attributes are copied.
β‘ Why “builtin” strategies are faster
The builtin strategies use Node.js’s built-in file copying, which runs
entirely within the PhotoStructure process. The native strategies spawn a
separate process (cp, ditto, or PowerShell), which has overhead from:
- Process creation (forking)
- Security scanners (like Windows Defender or macOS Gatekeeper) checking the spawned process
- Inter-process communication
For copying many small files, this overhead adds up significantly.
π΄ Deprecated settings
Previous versions of PhotoStructure used two boolean settings:
fileCopyOnlyNative- forced use of native copy commandsfileCopyWithReflink- enabled reflink support
These settings are now deprecated. If you have them in your settings.toml,
PhotoStructure will automatically migrate them:
fileCopyOnlyNative = truebecomesfileCopyStrategy = "native-preserve"fileCopyWithReflink = truebecomesfileCopyStrategy = "builtin-reflink"- Otherwise becomes
fileCopyStrategy = "builtin"
You can safely remove the old settings from your configuration files.
β Verifying file copies
PhotoStructure can verify that copied files match their originals by comparing SHA checksums (cryptographic fingerprints). This catches rare but serious problems like:
- Silent data corruption during transfer
- Network glitches on NAS systems
- Filesystem bugs
- Failing storage hardware
π How verification works
- Before copying, PhotoStructure computes the SHA checksum of the source file
- After copying, it computes the SHA of the destination file
- If the checksums don’t match, the copy is considered failed
- PhotoStructure retries the comparison briefly to handle network filesystems where writes may not be immediately visible
βοΈ The fileCopyVerify setting
Copy verification is controlled by the fileCopyVerify setting:
fileCopyVerify = true
Or via environment variable:
PS_FILE_COPY_VERIFY="true"
Default: true (verification enabled)
π€ Should I disable verification?
Verification is enabled by default because data integrity is critical for irreplaceable photos and videos. However, you might consider disabling it if:
- You’re doing a large initial import and want maximum speed
- Your storage is already protected by checksumming (ZFS, btrfs with scrubbing)
- You’ve verified your hardware and network are reliable
We recommend: Leave it enabled. The performance cost is one extra file read per copy. If a copy fails verification, you’ll know immediately rather than discovering corruption months or years later.
π¨ Troubleshooting
β οΈ “File copy test failed” in health check
If you see this error on the PhotoStructure health page:
- Check that PhotoStructure has write permission to your library directory
- Check that your filesystem isn’t full
- Try setting
fileCopyStrategytonativeas a fallback - Check your system logs for more detailed error messages
π’ Copies are very slow
If file copies are slower than expected:
- Make sure you’re using a
builtinstrategy (notnative) - If using a NAS, check your network connection speed
- Consider whether your source or destination drives are the bottleneck
π Files have wrong permissions after copy
The builtin strategies don’t preserve file permissions. If you need
permissions preserved:
- Set
fileCopyStrategy = "native-preserve" - On TrueNAS/ZFS, you may need to set
aclmode=passthrough(see above)
See also
- How do I safely store my files? - NAS recommendations and backup strategies
- What is a volume? - Understanding how PhotoStructure sees your storage
- Using environment variables - How to configure PhotoStructure via environment variables
