Read-Only Gallery CLI Sync Fails: Status Code 400 File Does not exist within user's external path
I found several similar posts but neither assisted me in resolving my issue as my setup is on docker desktop (Windows 11) not TrueNAS or a Linux distro. Any help the community can offer would be much appreciate. Thanks!
On my Windows 11 machine I have the following directory which I mounted in the docker desktop immich container: D:\Photos
This is the dockercompose.yml line for the mount paths under immich-server and immich-microservices:
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
- "D:/Photos:/Photos:ro"
Within the immich web page I added the following directory as the external path:
D:/Photos
Within docker desktop I went to the immich-server container, opened the terminal, and entered the following command:
immich upload --key <key obtained from the immich user settings page> --server http://<server IP>:2283/api /Photos --recursive --import
Upon entering the command I see the following:
Checking connectivity with Immich instance...
Server status: OK
Checking credentials...
Login status: OK
Successful authentication for user <user email>
Indexing local assets...
Indexing complete, found 23218 local assets
Comparing local assets with those on the Immich instance...
A total of 23218 assets will be uploaded to the server
17 Replies
When I select yes to the import prompt I eventually see errors like the following for each photo:
Error asset: {
file: '/Photos/Work/image000000 (1).jpg',
reason: Error: Request failed with status code 400
at createError (/usr/src/app/node_modules/axios/lib/core/createError.js:16:15)
at settle (/usr/src/app/node_modules/axios/lib/core/settle.js:17:12)
at IncomingMessage.handleStreamEnd (/usr/src/app/node_modules/axios/lib/adapters/http.js:322:11)
at IncomingMessage.emit (node:events:526:35)
at endReadableNT (node:internal/streams/readable:1359:12)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
config: {
transitional: [Object],
adapter: [Function: httpAdapter],
transformRequest: [Array],
transformResponse: [Array],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: Infinity,
maxBodyLength: Infinity,
validateStatus: [Function: validateStatus],
headers: [Object],
method: 'post',
maxRedirects: 0,
url: 'http://192.168.1.2:2283/api/asset/import',
data: '{"deviceAssetId":"image000000(1).jpg-547508","deviceId":"CLI","fileCreatedAt":"2023-04-02T17:35:12.822Z","fileModifiedAt":"2023-04-02T17:35:12.822Z","isFavorite":"false","fileExtension":".jpg","duration":"0:00:00.000000","isReadOnly":"true","assetPath":"/Photos/Work/image000000 (1).jpg"}'
},
request: ClientRequest {
_events: [Object: null prototype],
_eventsCount: 3,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: false,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
strictContentLength: false,
_contentLength: 312,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: false,
socket: [Socket],
_header: 'POST /api/asset/import HTTP/1.1\r\n' +
'Accept: application/json, text/plain, /\r\n' +
'Content-Type: application/json\r\n' +
'x-api-key: ISmOr6niTZGtg8orFI9czLs0NGRv8lgJ3B42VJr0\r\n' +
'User-Agent: axios/0.26.1\r\n' +
'Content-Length: 312\r\n' +
'Host: 192.168.1.2:2283\r\n' +
'Connection: close\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: [Agent],
socketPath: undefined,
method: 'POST',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
joinDuplicateHeaders: undefined,
path: '/api/asset/import',
_ended: true,
res: [IncomingMessage],
aborted: false,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: '192.168.1.2',
protocol: 'http:',
[Symbol(kCapture)]: false,
[Symbol(kBytesWritten)]: 0,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: [Object: null prototype],
[Symbol(errored)]: null,
[Symbol(kHighWaterMark)]: 16384,
[Symbol(kRejectNonStandardBodyWrites)]: false,
[Symbol(kUniqueHeaders)]: null
},
response: {
status: 400,
statusText: 'Bad Request',
headers: [Object],
config: [Object],
request: [ClientRequest],
data: [Object]
},
isAxiosError: true,
toJSON: [Function: toJSON]
},
response: {
statusCode: 400,
message: "File does not exist within user's external path",
error: 'Bad Request'
}
}
what is the external path in your user setting in the adminstrator setting
I advise to spin up WSL and use it to import you library
D:\Photos
I can look into WSL
I honestly don't know how well windows's path translate to Linux path
since the left hand side and the right hand side path need to match
I saw that note in that documentation and wondered if that was an issue.
I believe so
there is another way you can try
we bundle the cli tool into the server's image
so you can attach to the server's container and run the
immich upload... --import
command directly from the containerWithin docker desktop I can browse the /Photos mount and see the subdirectories and photos
I think that is how I am running the command. I just go into docker desktop. Select the immich-server container and then select terminal and enter it from there.
yes, please try that and let me know if it work
You external path setting should be
/Photos
as wellSo I did try to update the external path to /Photos and I rerun the command and it did not accept that entry. I forget what it said but I changed it back when it failed.
Did you rerun the command from the container or from your Windows shell?
I have always run it from within the container. I'm not sure how to do it from the window shell.
ah
hmm
The error message is about the file not being in your external path. That means everything else is working correctly (it finds the file, etc)
You just need to set the external path correctly and try again
I'll update the external path again and try it again
It's working!
I wonder if I entered it as \Photos instead of /Photos the first time I tried it
Nonetheless, thank you both for your prompt assistance it is much appreciated. You guys have done an excellent job with this and I am super excited to be able to check it out.
Also, I was looking at the donation page and I was somewhat confused by the one time payment option.
It lets me select a higher amount than the $5 option but when I click the button the next page only shows the $5 option instead of the higher amount.
I've never donated through GitHub before so maybe I am missing something.
I am not sure about this 😛
No problem, I'll look into it more and if necessary I'll do a recurring sponsorship for a while instead. I definitely want to support the project.
Thank you ❤️