laurent22/joplin · error · Error
Could not access data on server "${options.path()}"
Error message
Could not access data on server "${options.path()}" What it means
Thrown by SyncTargetJoplinServer.checkConfig during a write/read round-trip test: it put('testing.txt', 'testing') then get('testing.txt') and the returned content is not 'testing'. This catches silent data corruption or server-side rewriting (e.g. a proxy that mangles bodies) that stat-only checks would miss.
Source
Thrown at packages/lib/SyncTargetJoplinServer.ts:133
if (r) {
const parsed = JSON.parse(r);
if (parsed) {
output.ok = true;
return output;
}
}
} catch (error) {
// Ignore because we'll use the next test to check for sure if it
// works or not.
staticLogger.warn('Could not fetch or parse info.json:', error);
}
// This is a more generic test, which writes a file and tries to read it
// back.
try {
await fileApi.put('testing.txt', 'testing');
const result = await fileApi.get('testing.txt');
if (result !== 'testing') throw new Error(`Could not access data on server "${options.path()}"`);
await fileApi.delete('testing.txt');
output.ok = true;
} catch (error) {
output.errorMessage = error.message;
if (error.code) output.errorMessage += ` (Code ${error.code})`;
}
} finally {
fileApi.requestRepeatCount_ = previousRequestRepeatCount;
}
return output;
}
protected async initFileApi() {
return initFileApi(SyncTargetJoplinServer.id(), this.logger(), {
path: () => Setting.value('sync.9.path'),
userContentPath: () => Setting.value('sync.9.userContentPath'),
username: () => Setting.value('sync.9.username'),View on GitHub (pinned to 2654b33620)
Solutions
- Verify the server URL and base path in sync settings point to the real Joplin Server endpoint.
- Check any reverse proxy (nginx, Cloudflare) for response body rewriting or charset overrides — disable auto-minify / Rocket Loader etc.
- Ensure reads and writes resolve to the same path (no path-rewrite rules that differ for PUT vs GET).
- Try a direct connection to the Joplin Server without the proxy to isolate the cause.
Example fix
# before: Cloudflare in front of Joplin Server, rewriting bodies # after: in Cloudflare, disable 'Auto Minify' and 'Rocket Loader' for the Joplin Server route, # and confirm the sync URL is https://server/api/files/...
Defensive patterns
Strategy: try-catch
Validate before calling
// Outside checkConfig, you can pre-flight with a manual round-trip.
await fileApi.put('probe.txt', 'x');
const back = await fileApi.get('probe.txt');
if (back !== 'x') throw new Error('Server is rewriting payloads — check reverse proxy');
await fileApi.delete('probe.txt'); Type guard
const isPassthroughPayload = (sent, received) => sent === received;
Try / catch
try { await SyncTargetJoplinServer.checkConfig(options); }
catch (e) { if (/Could not access data on server/.test(e.message)) { /* inspect proxy / path config */ } else throw e; } Prevention
- Point sync directly at the Joplin Server API path; remove body-rewriting middleware (minify, Rocket Loader, charset override).
- In front of the server, run a curl round-trip (PUT then GET) to catch silent rewrites before configuring Joplin.
When it happens
Trigger: checkConfig() puts 'testing.txt', reads it back, and `result !== 'testing'`. Caused by an intermediate proxy rewriting content, a misconfigured Joplin Server returning HTML errors as 200, or a server that stores content under a different path than it reads.
Common situations: Server URL points to a reverse proxy that injects boilerplate; wrong base path so reads hit a different namespace than writes; server is actually a different Joplin Server instance than expected; encoding/charset conversion.
Related errors
- AWS S3 bucket not found: ${SyncTargetAmazonS3.s3BucketName()
- WebDAV directory not found: ${options.path()}
- uploadBlob: ${method} ${url}: ${error.toString()}
- lockError
- Could not verify the share status of this notebook - abortin
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/45cc9b3a79e111ec.
Report an issue: GitHub.