RocketChat/Rocket.Chat · error · Error

Error sending file to apps

Error message

Error sending file to apps

What it means

The Webdav upload stores pipe a read stream from the WebDAV server; any stream 'error' event logs 'An error ocurred when fetching the file' via SystemLogger and responds 503 with an empty body. 503 (not 404) marks the upstream store as the problem: connectivity, credentials, or the remote file — Rocket.Chat could not retrieve bytes from WebDAV.

Solutions

  1. Verify the WebDAV server is reachable and credentials valid — re-save the FileUpload_Webdav_* settings to force reconfiguration
  2. Correlate with the SystemLogger 'An error ocurred when fetching the file' entry at the same timestamp to confirm the store is the failure point
  3. Re-upload or re-sync files missing on the WebDAV server
  4. Reproduce with an external WebDAV client if the error persists; watch for partial content already written before the error

Example fix

// before: single attempt, surface as 500
const res = await fetch(fileUrl);
// after: retry transient 503s from the store
for (let i = 0; i < 3; i++) {
	const r = await fetch(fileUrl);
	if (r.status !== 503) return r;
	await new Promise((ok) => setTimeout(ok, 2 ** i * 500));
}
throw new Error('webdav store unavailable');
Defensive patterns

Strategy: retry

Validate before calling

// preflight the upstream before serving
await fetch(settings.get('FileUpload_Webdav_Server_URL'), { method: 'OPTIONS' }).catch(() => { /* mark store unhealthy; fail fast with a clear message */ });

Try / catch

Attach an 'error' handler on the read stream; on error, retry the whole getReadStream with exponential backoff (2-3 attempts) for transient 503s; abort retry on auth failures (401/403 from WebDAV) and surface the credential problem instead.

Prevention

When it happens

Trigger: FileUpload_Webdav_Server_URL unreachable, TLS-invalid, or slow to the point of stream failure; FileUpload_Webdav_Username/Password wrong or rotated (settings are re-read via settings.watchByRegex); the remote file was deleted; connection dropped mid-transfer after partial data was written.

Common situations: WebDAV credential rotation not mirrored into settings; firewall/DNS changes breaking reachability; WebDAV server maintenance windows; partially uploaded files that open a stream then error.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/ea5a9b0ee93d0e98. Report an issue: GitHub.

Appendix: source

Thrown at apps/meteor/app/apps/server/bridges/listeners.ts:262

				return this.defaultEvent(args);
		}
	}

	async defaultEvent(args: HandleDefaultEvent): Promise<unknown> {
		return this.orch.getManager().getListenerManager().executeListener(args.event, args.payload[0]);
	}

	async uploadEvent(args: HandleFileUploadEvent): Promise<void> {
		const [{ file, content }] = args.payload;

		const tmpfile = path.join(this.orch.getManager().getTempFilePath(), crypto.randomUUID());

		if (typeof content === 'string') {
			// If content is a string, we assume it's a path and create a symlink to avoid file duplication
			await fs.promises.symlink(content, tmpfile, 'file').catch((err) => {
				this.orch.getRocketChatLogger().error({ msg: `AppListenerBridge: Could not create symlink at ${tmpfile}`, err });

				throw new Error('Error sending file to apps', { cause: err });
			});
		} else {
			// Otherwise, we write the buffer content to a temporary file
			await fs.promises.writeFile(tmpfile, content).catch((err) => {
				this.orch.getRocketChatLogger().error({ msg: `AppListenerBridge: Could not write temporary file at ${tmpfile}`, err });

				throw new Error('Error sending file to apps', { cause: err });
			});
		}

		try {
			const uploadDetails = {
				name: file.name || '',
				size: file.size || 0,
				type: file.type || '',
				rid: file.rid || '',
				userId: file.userId || '',
				visitorToken: file.token,

View on GitHub (pinned to b2c16d5842)