mirror of
https://github.com/immich-app/immich.git
synced 2026-03-02 22:57:45 -05:00
Read-only external library metadata edits silently fail #3241
Open
opened 2026-02-20 02:06:50 -05:00 by deekerman
·
26 comments
No Branch/Tag specified
main
renovate/typescript-projects
release/next
renovate/github-actions
chore/translations
push-nwxlpmyzkyrl
push-wzwotsylzylq
push-zpwsovysllvn
push-zunuwtznrlpm
renovate/opentofu-1.x
renovate/node
push-rsywxvptwxuv
renovate/prom-prometheus
renovate/docker.io-valkey-valkey-9
push-suusrsrnmzrp
push-xyozownmuwqp
csp-policy
uhthomas/fix-mobile-video-state
uhthomas/fix-mobile-hero-height
feat/use-native-clients
uhthomas/chore-mobile-simplify-scroll
feat/mobile-edit-3-mobile-sync-handling
feat/panorama-tiles
refactor/zod-migration
fix/maintenance-reload
refactor/restores-file-interceptor
uhthomas/fix-mobile-inconsistent-asset-detials-background
postgres-socketio
claude/auto-screenshot-web-changes-Y7efI
visual-review/pr-26535
push-lvyturrtwkrq
feat/notification
feat/library-offline-stats
feat/checksum-algorithm-indicator
feat/library-offline-count
uhthomas/feat-mobile-search-results
fix/bring-back-globalkeys
fix/map-webgl-error
feat/mobile-ocr
feat/custom-date-range
fix/mobile-video-aspect-ratio
fix/ml-ocr-batch-size
fix/timeline-rtl
feat/integrity-checks-izzy
uhthomas/fix-mobile-search-results
renovate/flutter
uhthomas/feat-sort-smart-search
renovate/github-cqlabs-homebrew-dcm-1.x
feat/video-player
feat/mobile-editing
refactor/remove-replace-with-upload
uhthomas/chore-mobile-maplibre
uhthomas/mobile-fix-asset-details-album-pop
feat/crawl-wrapper
feat/open-in-browser
push-skvzqoozqkpl
feat/edit-filters
fix/locale-settings-desc
feat/pg-queue
refactor/asset-upload
renovate/connectivity_plus-7.x
better-project-structure
uhthomas/mobile-feat-asset-viewer-details
fix/ml-rocm-build
fix/25803
feat/asset-file-apis
midzelis/wip
feature/bottom-buttons-order
sqlite_thumbs
fix-keep-correct-ios-shared-album-asset
fix-memory-generation-and-display
push-vpxwmwwxwnvw
fix-migration-width-height
revert/prettier-translations
shared-deep-link-handler
feat/thumbnail-native-clients
feat/platform-clients
fix/foreground-cloud-sync
filter-by-person
feat/csp
refactor/sidebar
fix/disable-editing
fix/view-timeline-deeplink
image-zoom-on-slow-connection
fix/merged-edited-assets
open-api-fix
feat/create-job-with-dto
use-toast-primary
feat/vitest-4
feat/ios-fastlane-match
match-signing
fix-update-time-update-timeline
feat/modal-routes
feature/mobile-view-asset-owner
feat/system-settings
feature/show-activity-count
better-info-in-asset-viewer
fix/all-people-count
feat/location-favorites
feature/rearrange-buttons-2
fix/download-storage-template
feat/kb-shortcuts-mobile
fix/people-count
push-qolzzzzxrvvn
chore/originals-in-asset-files
feat/asset-size-columns
ben/tree-a11y
new-search-filter-ui
refactor/expectSelectedReadonly
refactor/mobile-grdb
push-qvuktpxmkknu
feat/mobile-native-local-sync
refactor/timeline_ops
fix/scrubber_end
feat/version.txt
feat/context-menus
feat/server-chunked-uploads
refactor/virtualsegment
refactor/rename_daymonth_groups
fix/restrict-android-bg-worker
feat/android-periodic-worker
fix-remote-sync-clean-up
refactor/timeline_move_ops
fix/timeline_split_selectable
feat/keyboard_actions_help_modal
feat/static_frontend
feat/notification-warnign-android
feat/plugins2
feat/plugins
test/create-workflow-token-action
fix/docs-force
debug/search-result-similarity
debug/cf-chunked-uploads
feat/eslint_rule
feat/search-filter-album/web
refactor/timeline_photostream
refactor/timelineasset_asset
feat/session-permissions
feat/timeline_photostream_assetnav
feat/timeline_minor_optimize
feat/timeline_perf_nocomp
feat/timeline_search_results_actions
feat/timeline_search_results_page
fix/timeline_padding
fix/timeline_search_reactivity_warnings
feat/timeline_scrollbar
feat/timeline_stream_withviewer
fix/timeline_back_forth_nav
refactor/timeline_photostream_component
fix/generated-files-checks
fix/locate-button-local
chore/base-image-mimalloc
refactor/timeline_assetlayout
refactor/timeline_selectable
refactor/timeline_aware_actions
refactor/timeline_monthsegment
feat/remove-old-pages
chore/deps-gradle
tmp_photostream
tmp/lcms
feat/mobile-dynamic-thumbnails
fix/mobile-finer-thumbnail-concurrency
refactor/timeline1
refactor/extract_photostream
refactor/rename_load_api
refactor/timeline2
refactor/timeline3
feat/multi-select-asset-viewer
feat-no-thumbhash-cache
refactor/asset_grid
feat/faster-access-checks
fix/18991
fix/19543
chore/temp-remove
fix/21419
feat/mobile-hdr-images
chore/update-mise-lockfile
feat/mise-server-checks
feat/mise-ci
feat/windows-2025
feat/dev_cli
refactor/mobile-migrate-clients
fix/map-theme
fix/require-checkbox
chore/use_swc
feat/efficient-thumbnail-decoding
refactor/mobile-thumbhash
refactor/mobile-thumbhash-new
feat/beta-background-upload
fix/beta-timeline-memories-setting
fix/failed-uploads-not-removed
feat/mobile-shared-album
feat/groups
drift-map-page
drift-auth-user-sync
fix/disable-memory
feat/add-to-album-action
edit-date-time-action
drift-people-page
sqlite-remove-isIn
chore/required-reviewers
refact/asset-manager
fix/folder-sort
pnpm
feat/widget-multiple-server-urls
chore/medium-tests-dbname
fix/web-no-iterator-find
fix/map-pan-interruption
track-livephotos
timeline_events
chore/oxlint-migration
feat/maintenance-worker
feat/dav
chore/demo-snapshot
refactor/server-side-dedupe
feat/integrity-checks
dev/recognition-eval
lighter_buckets_test
perf/postgres-queue
postgres-queue
focus_rings
refactor/web-stores-1
refactor/add-to-taken
feat/sort-places
vet
tmp/demo-snapshot-preview
fix/server-migration-file-extension
fix/asset-update-race-condition
rknn-toolkit-lite2
refactor/mobile-split-up-search-page
feature/Add-rocm-support-for-machine-learning
feat/rocm
chore/async-hash-file
feat/shared-link-view-count
feat/rotation
feat/graphql
feat/job-ids
feat/ignore-library-permission-error
feat/docker-compose-builder
feat/kysely-typeorm
mobile/onboarding
no-video-player
fix/server-qsv-output-format
chore/server-geodata-tweaks
mobile/native-video-player-no-hero
feat/xxhash
fix/docs-concurrency
feat/local-tileserver
refactor/exif-orientation
original-path-infix
refactor/mobile/login-form-1
feat/server-editor-endpoints
fix/server-qsv-vbr
fix-mobile-db-problems
feat/ml-armnn-conversion
feat/mobile/backup-with-album-info
feat/fast-initial-sync-1
chore/handle-output_dims
feat/unassign-faces
feat/shortcuts-on-asset-grid
feat/capacitor-mobile-app-poc
feat/server-nvenc-hw-decoding
fix/mobile-fetch-non-archive
web/automation-ui
feat/mobile-server-endpoint-save-dropdown
object-storage
feat/memories-animations
dev/metrics
ml/tflite
feat/ml-export-cli
v2.5.6
v2.5.5
v2.5.4
v2.5.3
v2.5.2
v2.5.1
v2.5.0
v2.4.1
v2.4.0
v2.3.1
v2.3.0
v2.2.3
v2.2.2
v2.2.1
v2.2.0
v2.1.0
v2.0.1
v2.0.0
v1.144.1
v1.144.0
v1.143.1
v1.143.0
v1.142.1
v1.142.0
v1.141.1
v1.141.0
v1.140.1
v1.140.0
v1.139.4
v1.139.3
v1.139.2
v1.139.1
v1.139.0
v1.138.1
v1.138.0
v1.137.3
v1.137.2
v1.137.1
v1.137.0
v1.136.0
v1.135.3
v1.135.2
v1.135.1
v1.135.0
v1.134.0
v1.133.1
v1.133.0
v1.132.3
v1.132.2
v1.132.1
v1.132.0
v1.131.3
v1.131.2
v1.131.1
v1.131.0
v1.130.3
v1.130.2
v1.130.1
v1.130.0
v1.129.0
v1.128.0
v1.127.0
v1.126.1
v1.126.0
v1.125.7
v1.125.6
v1.125.5
v1.125.4
v1.125.3
v1.125.2
v1.125.1
v1.125.0
v1.124.2
v1.124.1
v1.124.0
v1.123.0
v1.122.3
v1.122.2
v1.122.1
v1.122.0
v1.121.0
v1.120.2
v1.120.1
v1.120.0
v1.119.1
v1.119.0
v1.118.2
v1.118.1
v1.118.0
v1.117.0
v1.116.2
v1.116.1
v1.116.0
v1.115.0
v1.114.0
v1.113.1
v1.113.0
v1.112.1
v1.112.0
v1.111.0
v1.110.0
v1.109.2
v1.109.1
v1.109.0
v1.108.0
v1.107.2
v1.107.1
v1.107.0
v1.106.4
v1.106.3
v1.106.2
v1.106.1
v1.106.0
v1.105.1
v1.105.0
v1.104.0
v1.103.1
v1.103.0
v1.102.3
v1.102.2
v1.102.1
v1.102.0
v1.101.0
v1.100.0
v1.99.0
v1.98.2
v1.98.1
v1.98.0
v1.97.0
v1.96.0
v1.95.1
v1.95.0
v1.94.1
v1.94.0
v1.93.3
v1.93.2
v1.93.1
v1.93.0
v1.92.1
v1.92.0
v1.91.4
v1.91.3
v1.91.2
v1.91.1
v1.91.0
v1.90.2
v1.90.1
v1.90.0
v1.89.0
v1.88.2
v1.88.1
v1.88.0
v1.87.0
v1.86.0
v1.85.0
v1.84.0
v1.83.0
v1.82.1
v1.82.0
v1.81.1
v1.81.0
v1.80.0
v1.79.1
v1.79.0
v1.78.1
v1.78.0
v1.77.0
v1.76.1
v1.76.0
v1.75.2
v1.75.1
v1.75.0
v1.74.0
v1.73.0
v1.72.2
v1.72.1
v1.72.0
v1.71.0
v1.70.0
v1.69.0
v1.68.0
v1.67.2
v1.67.1
v1.67.0
v1.66.1
v1.66.0
v1.65.0
v1.64.0
v1.63.2
v1.63.1
v1.63.0
v1.62.1
v1.62.0
v1.61.0
v1.60.0
v1.59.1
v1.59.0
v1.58.0
v1.57.1
v1.57.0
v1.56.2
v1.56.1
v1.56.0
v1.55.1
v1.55.0
v1.54.1
v1.54.0
v1.53.0
v1.52.1
v1.52.0
v1.51.2
v1.51.1
v1.51.0
v1.50.1
v1.50.0
v1.49.0
v1.48.1
v1.48.0
v1.47.3
v1.47.2
v1.47.1
v1.47.0
v1.46.1
v1.46.0
v1.45.0
v1.44.0
v1.43.1
v1.43.0
v1.42.0_65-dev
v1.41.1_64-dev
v1.41.0_64-dev
v1.40.1_63-dev
v1.40.0_63-dev
v1.39.0_61-dev
v1.38.2_60-dev
v1.38.1_60-dev
v1.38.0_60-dev
v1.37.0_58-dev
v1.36.2_56-dev
v1.36.1_55-dev
v1.36.0_55-dev
v1.35.0_54-dev
v1.34.0_53-dev
v1.33.1_52-dev
v1.33.0_52-dev
v1.32.1_51-dev
v1.32.0_50-dev
v1.31.1_49-dev
v1.31.0_49-dev
v1.30.2_48-dev
v1.30.0_46-dev
v1.29.6_45-dev
v1.29.6_44-dev
v1.29.5_44-dev
v1.29.4_44-dev
v1.29.3_43-dev
v1.29.2_43-dev
v1.29.1_43-dev
v1.29.0_42-dev
v1.28.4_41-dev
v1.28.4_42-dev
v1.28.3_41-dev
v1.28.2_40-dev
v1.28.1_39-dev
v1.28.0_38-dev
v1.27.0_37-dev
v1.26.0_36-dev
v1.25.0_35-dev
v1.24.0_34-dev
v1.23.0_33-dev
v1.22.0_32-dev
v1.21.1_31-dev
v1.21.0_31-dev
v1.20.3_30-dev
v1.20.2_30-dev
v1.20.1_30-dev
v1.20.0_30-dev
v1.19.1_29-dev
v1.19.0_29-dev
v1.18.0_27-dev
v1.17.0_25-dev
v1.16.0_23-dev
v1.15.1_21-dev
v1.15.0_21-dev
v1.14.0_21-dev
v1.13.0_20-dev
v1.12.0_18-dev
v1.11.0_17-dev
v1.10.0_15-dev
v1.9.1_14-dev
v1.9.0_13-dev
v1.8.0_12-dev
v1.7.0_11-dev
v1.6.0_10-dev
v1.5.1+9-dev
v1.5.0+8-dev
v1.4.0+7-dev
v1.4.0+6-dev
v1.4.0-dev
v1.3.0-dev
v1.3.1-dev
v0.6-dev
v0.5-dev
v0.4-dev
v0.3-dev
v0.2-dev
first-android-release
Labels
Clear labels
accessibility
changelog:enhancement
changelog:security
changelog:skip
changelog:translation
cli
date-time
dependencies
documentation
external-library
format
good first issue
mobile-beta
mobile-beta
mobile-beta
needs-answer
nice to have
sharing
tech-debt
📱mobile
🖥️web
🗄️server
🧠machine-learning
No labels
accessibility
changelog:enhancement
changelog:security
changelog:skip
changelog:translation
cli
date-time
dependencies
documentation
external-library
format
good first issue
mobile-beta
mobile-beta
mobile-beta
needs-answer
nice to have
sharing
tech-debt
📱mobile
🖥️web
🗄️server
🧠machine-learning
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set.
Reference
starred/immich#3241
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @pyorot on GitHub (Jun 22, 2024).
Originally assigned to: @etnoy on GitHub.
The bug
This has been discussed several times before, but there is an unintuitive behaviour where if a user edits metadata of an asset in an external library that's mounted as read-only (say by forgetting it's read-only or believing the edit would be stored in the database or generated files) then the edit silently fails.
A simple solution that came up in discussion is to issue a generic asynchronous popup to the client saying "failed to save metadata for <asset filename>: file system is read-only" or similar (and the log should mention "read-only" too).
The OS that Immich Server is running on
Debian 12
Version of Immich Server
v1.106.3
Version of Immich Mobile App
n/a
Platform with the issue
Your docker-compose.yml content
Your .env content
Reproduction steps
Relevant log output
Additional information
No response
@wolginm commented on GitHub (Jun 23, 2024):
Its funny, I've been 'reproducing' this bug for a few days now and pulling out may hair in the process.
I agree, that there should be some indication on the external library, or on the file. Maybe even gray out the options so the user knows whats going on. The silent fail felt very random.
I'm just glad its not me 😄.
I am going to try and loosen the permissions on the folder and see if it solves the issue for me.
EDIT: It did.
@ShinyYellowBanana commented on GitHub (Jul 7, 2024):
I also seem to have silently failed here. I havent confirmed issue, but will verify later.
@kvalev commented on GitHub (Sep 1, 2024):
What seems to be a bit weird is that when you add new tags, those will be saved, even tho xmp writing fails. However changing the date or the location straight up doesnt work. It will be nice if the behavior is consistent.
@pyorot commented on GitHub (Sep 1, 2024):
Does this mean the tags go in the database? 🤔
@bo0tzz commented on GitHub (Sep 2, 2024):
The reason that happens is that extracting date or location from the file metadata overwrites what is in the database because an asset can only have one date or location, which doesn't apply to tags.
@jrasm91 commented on GitHub (Sep 2, 2024):
It should apply to tags as well. Tags are written to xmp and replaced on a subsequent metadata extraction.
@pypeaday commented on GitHub (Sep 19, 2024):
FWIW I am having this issue with tags on my RO external library
@pypeaday commented on GitHub (Sep 19, 2024):
can the xmp files or whatever be written somewhere else?
@basicfu commented on GitHub (Sep 27, 2024):
+1 can the xmp files or whatever be written somewhere else?
I need to back up my gallery, but I don't want to see the xmp file when previewing through NAS
@bo0tzz commented on GitHub (Sep 28, 2024):
They're sidecar files, storing them somewhere disconnected from the media doesn't really make sense.
@acbarrentine commented on GitHub (Oct 5, 2024):
When the tag feature first went in, I was able to tag external (read-only) pictures. In subsequent updates, I have lost that functionality. Tags appear to apply, then disappear a few seconds later. In the log, I see the same kind of warnings reported above.
I could make the file system writeable, but I'd prefer not to. Something knows tags for my external files in that read-only file system made during the span where it worked. I suspect something went wrong with a revision and it is now trying to send that data to the .xmp files incorrectly
@Stronginthearm42 commented on GitHub (Oct 9, 2024):
+1
It seems to me that the "correct" option would be to store changed metadata for ro assets in the db.
@pyorot commented on GitHub (Oct 9, 2024):
Ah but then the user would need to be told that that new metadata would only be reflected in immich rather than portably
@Stronginthearm42 commented on GitHub (Oct 10, 2024):
Yes, but since the library is read-only, this shouldn't be surprising.
@anthonynogales commented on GitHub (Oct 27, 2024):
I think that all libraries, not just read-only ones, should have metadata like descriptions, tags, and ratings stored in the database by default. This approach would provide a central, reliable repository for metadata management, and users could then elect to export this metadata to individual XMP sidecar files for all images or an individual image if desired. This flexibility would allow for more efficient organization and metadata handling across all library types without altering the original files unless chosen explicitly by the user.
@jrasm91 commented on GitHub (Dec 28, 2024):
If you re-run metadata extraction on the file again it would silently overwrite the value in the database if it never was persisted to an xmp file
@patmagauran commented on GitHub (Feb 6, 2025):
As a potential workaround to this, I setup an overlay mount for immich to access my external library from. That way the underlying files aren't modified; however sidecar data is still maintained by immich. I haven't been running it for long enough to notice any side-effects, but it should work well for a layer of separation.
For docker compose:
The overlayFS works by taking the contents of the 'lower' directory and creating a virtual file system on top which is accessible from the container. The 'upperdir' houses all the changed files and the 'workdir' houses files that are in the process of being changed (kind of like file level COW).
Since Immich doesn't write metadata to the original file, the overlay should take up very little space as it would only store xmps (As well as any changes due to deletion or editing).
Credit for how to use the overlayfs as a volume mount: https://stackoverflow.com/questions/29550736/can-i-mount-docker-host-directory-as-copy-on-write-overlay
@pyorot commented on GitHub (Feb 7, 2025):
i like the idea of implementing this as a persistent overlay, as long as there’s a system by which the data could optionally be merged into the originals (same as if the mount were rw rather than ro). bo0tzz suggested to me just now to use Exiftool, but the question is how much this process can be automated. for example, whether this overlay xmp set can be exported into a set of files that retain adequate links with their assets to then be mergeable in one step rather than #number-of-assets steps
@Nightmaren commented on GitHub (Feb 22, 2025):
I have been using the overlayFS method heavily over the past week. I have been adding files to my external library's directory, scan them via Immich, then proceed to go through each one and manually tag them. Everything is working as expected, with the sidecars being created in the upper directory.
However, one side-effect I have found pertains to the way the external library is scanned. I typically have Immich rescanning it daily on a cron job, but even if I ask it to scan manually via the admin panel, it will not notice the presence/absence of additional photos. Upon restarting, and then rescanning, photos are updated as expected.
I believe this has to do with the way docker manages the lower directory's files when using the overlayFS.
@alextran1502 commented on GitHub (Nov 9, 2025):
This is no longer relevant with the new implementation, please open a new issue if it is still persisted@mikehardy commented on GitHub (Jan 6, 2026):
Very interesting! Just ran into this myself. I understand that philosophically the sidecar file should live next to the file. Adults can disagree but a firm opinion is clarifying, so - fine as far as it goes.
Seems a popup would be great as a warning, warning the non-documentation-reading regular users of our systems to be aware of the limitation.
Or, an implementation that went ahead and updated the database, followed by a popup on "refresh metadata" saying "this asset is from an external library that is read-only but has local modifications, refreshing metadata will overwrite the local modifications". In fact, it could even detect the changes between what the metadata refresh would do and what is local and show people a little diff panel per-changed-element similar to Calibre's metadata updater as you review downloaded metadata for changes (example image of same here in form of reasonably safe image search result link - was best I could find: https://duckduckgo.com/?q=calibre+review+downloaded+metadata+download+accept&iar=images&t=brave&iai=https%3A%2F%2Fwww.pctips.com%2Fwp-content%2Fuploads%2F2024%2F05%2Fcalibre-downloaded-metadata.jpg )
But it is easy for users to dream up features but PRs as well as dev time for feature maintenance are always scarce of course.
So, for the workaround - @Nightmaren - seems like you are trying the docker-side overlay FS style. You mention you have a need to restart the immich stack prior to rescans. Have you tried the similar-but-reversed host-side overlay FS style? It was mentioned in the stackoverflow (https://stackoverflow.com/a/50917037/9910298) as a separate answer and may give us the best of all worlds - read-only base image repository, writeable XMPs, and no need to restart the immich stack prior to external rescans.
If no one else has tried it I might. My repo is on a synology NAS which is linux I've got root to, so I should be able to make it work prior to the FS sharing out on the network to immich.
@P3TE04 commented on GitHub (Jan 26, 2026):
@mikehardy did that work for you? I think this is the next solution I try
@mikehardy commented on GitHub (Jan 26, 2026):
Hey @P3TE04 👋
If you mean this:
I have not yet - my family is currently operating under the knowledge no metadata edits will be saved, and that's bought me time to do billable work instead.
I'm still very interested in trying it, just no time yet. If you do try it and have results to share I'd love to hear it personally
Cheers
@P3TE04 commented on GitHub (Jan 30, 2026):
@mikehardy it looks like they may have solved our entire problem with the newest update! unless I'm doing something wrong. It does however seem that my files are still read only in immich, and yet I can add tags juuust fine :)
@mikehardy commented on GitHub (Jan 30, 2026):
Tags were always in the db its if you try to change things that were in exif like location or time I thought?
@P3TE04 commented on GitHub (Jan 30, 2026):
that's probably true, I'm really new to all of this still haha. I just know that whenever I'd add a tag to a photo from a read-only external library, it would only stay for a second then disappear, I figured its just because immich didn't have proper permissions in a read-only library. Maybe it was something else though!