gildas-lormeau/SingleFile · error · Error

error.message + " (WebDAV)"

Error message

error.message + " (WebDAV)"

What it means

saveWithWebDAV wraps any error from the WebDAV client upload (new WebDAV(url, username, password).upload(...)) and rethrows with an " (WebDAV)" suffix, preserving the original error as cause. It identifies the WebDAV save destination as the failure point.

Solutions

  1. Check error.cause for the HTTP status and verify the WebDAV URL is the full collection endpoint
  2. Re-enter username/password (or app password for Nextcloud/ownCloud)
  3. Confirm the server is reachable in a browser or via curl and its TLS certificate is valid
  4. Ensure the target directory exists on the WebDAV server

Example fix

// before
new WebDAV('myserver.com/dav', user, pass); // missing scheme
// after
new WebDAV('https://myserver.com/remote.php/dav/files/me', user, pass);
Defensive patterns

Strategy: validation

Validate before calling

const u = new URL(url);
if (!/^https?:$/.test(u.protocol)) throw new Error('WebDAV URL must be http(s)');
if (!username || !password) throw new Error('Missing WebDAV credentials');

Type guard

function hasWebDAVConfig(o) {
  try { const p = new URL(o.url).protocol; return (p === 'https:' || p === 'http:') &&
    !!o.username && !!o.password; } catch { return false; }
}

Try / catch

try {
  await saveWithWebDAV(taskId, filename, content, webdavOpts);
} catch (error) {
  if (error.message.endsWith('(WebDAV)')) {
    if (String(error.cause).includes('401')) { /* prompt for credentials */ }
  } else { throw error; }
}

Prevention

When it happens

Trigger: Any rejection inside WebDAV.upload(filename, content, {filenameConflictAction, prompt}) from downloadContent/downloadCompressedContent: connection failure, 401 auth error, 404 path not found, or abort.

Common situations: Wrong WebDAV server URL (missing https:// or wrong path); incorrect username/password; server certificate invalid (self-signed); Nextcloud/ownCloud app password revoked; firewall blocking the server.

Related errors


AI-assisted analysis of gildas-lormeau/SingleFile@517fb7c5cf (2026-09-01). Data as JSON: /api/errors/236ca2ca58652360. Report an issue: GitHub.

Appendix: source

Thrown at src/core/bg/downloads.js:508

			const client = new S3(region, bucket, accessKey, secretKey, domain);
			business.setCancelCallback(taskId, () => client.abort());
			return await client.upload(filename, blob, { filenameConflictAction, prompt });
		}
	} catch (error) {
		throw new Error(error.message + " (S3)", { cause: error });
	}
}

async function saveWithWebDAV(taskId, filename, content, url, username, password, { filenameConflictAction, prompt }) {
	try {
		const taskInfo = business.getTaskInfo(taskId);
		if (!taskInfo || !taskInfo.cancelled) {
			const client = new WebDAV(url, username, password);
			business.setCancelCallback(taskId, () => client.abort());
			return await client.upload(filename, content, { filenameConflictAction, prompt });
		}
	} catch (error) {
		throw new Error(error.message + " (WebDAV)", { cause: error });
	}
}

async function saveWithMCP(taskId, filename, content, serverUrl, authToken, { filenameConflictAction, prompt }) {
	try {
		const taskInfo = business.getTaskInfo(taskId);
		if (!taskInfo || !taskInfo.cancelled) {
			const client = new MCP(serverUrl, authToken);
			business.setCancelCallback(taskId, () => client.abort());
			return await client.upload(filename, content, { filenameConflictAction, prompt });
		}
	} catch (error) {
		throw new Error(error.message + " (MCP)", { cause: error });
	}
}

async function saveToGDrive(taskId, filename, blob, authOptions, uploadOptions) {
	try {

View on GitHub (pinned to 517fb7c5cf)