laurent22/joplin · error · Error
uploadBlob: ${method} ${url}: ${error.toString()}
Error message
uploadBlob: ${method} ${url}: ${error.toString()} What it means
Wraps any exception from the RNFetchBlob-backed mobile upload path (shim.uploadBlob). The catch on line 154 flattens the original error into 'uploadBlob: <method> <url>: <original>'. Like fetchBlob, the structured RNFetchBlob error and HTTP status are lost in the re-thrown generic Error.
Source
Thrown at packages/app-mobile/utils/shim-init-react/index.ts:155
const headers = options.headers ? options.headers : {};
const method = options.method ? options.method : 'POST';
try {
const response = await RNFetchBlob.config({
trusty: options.ignoreTlsErrors,
}).fetch(method, url, headers, RNFetchBlob.wrap(options.path));
// Returns an object that's roughly compatible with a standard Response object
return {
ok: response.respInfo.status < 400,
data: response.data,
text: response.text,
json: response.json,
status: response.respInfo.status,
headers: response.respInfo.headers,
};
} catch (error) {
throw new Error(`uploadBlob: ${method} ${url}: ${error.toString()}`);
}
};
shim.readLocalFileBase64 = async function(path) {
return RNFetchBlob.fs.readFile(path, 'base64');
};
shim.openUrl = url => {
return Linking.openURL(url);
};
shim.mobilePlatform = () => {
return Platform.OS as MobilePlatform;
};
shim.isAppleSilicon = () => {
return false;
};View on GitHub (pinned to 2654b33620)
Solutions
- Confirm options.path exists and is a native filesystem path (not a file:// URI) before calling uploadBlob.
- Check auth token validity and refresh if the server returns 401/403 (visible via shim.debugFetch on the same URL).
- For large files, verify the sync target's max upload size and increase it or chunk the resource.
- Pass ignoreTlsErrors only in dev for self-signed endpoints; for production install the correct root CA.
- Upgrade rn-fetch-blob/react-native-blob-util to match the React Native version.
Example fix
// before
await shim.uploadBlob(url, { path: resourcePath, method: 'POST' });
// after — guard the source file and capture status
if (!(await shim.fsDriver().exists(resourcePath))) throw new Error('Missing upload source');
const resp = await shim.uploadBlob(url, { path: resourcePath, method: 'POST', headers: authHeaders });
if (!resp.ok) throw new Error(`Upload rejected: ${resp.status}`); Defensive patterns
Strategy: retry
Validate before calling
if (!(await shim.fsDriver().exists(options.path))) throw new Error('uploadBlob: source missing');
if (!options.headers?.Authorization) throw new Error('uploadBlob: auth header missing');
await shim.uploadBlob(url, options); Type guard
function isUploadOptions(o) { return !!o && typeof o.path === 'string' && (!!o.method || true); } Try / catch
try {
const resp = await shim.uploadBlob(url, options);
if (!resp.ok) throw new Error(`upload ${resp.status}`);
} catch (e) {
if (/Network|timeout/i.test(e.message)) await backoffRetry(() => shim.uploadBlob(url, options));
else throw e;
} Prevention
- Verify the source file exists and is a native path before uploading.
- Keep auth tokens fresh; surface 401s for re-auth.
- Confirm the server's max upload size for large resources.
When it happens
Trigger: Uploading a resource blob to the sync target while offline; options.path does not exist or is unreadable; the server rejects the multipart body (auth failure, 413 payload too large, wrong content-type); TLS failure on the upload endpoint; RNFetchBlob.wrap() fails on a non-native path.
Common situations: E2EE sync upload to Joplin Server/Nextcloud/OneDrive with an expired token; uploading a large attachment exceeding server body limit; the source file was moved/deleted after the path was computed; reverse proxy timing out on slow upstream.
Related errors
- fetchBlob: ${method} ${url}: ${error.toString()}
- Item not found: ${itemId}
- No folder with id ${id}
- Could not download from ${modelUrl}: Error ${response.status
- Not a valid URL: ${url}
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/7276e4637daf3c4c.
Report an issue: GitHub.