laurent22/joplin · error · Error

Invalid date: ${lastModifiedString}

Error message

Invalid date: ${lastModifiedString}

What it means

Thrown by statFromResource_() right after parsing lastModifiedString with new Date(). If the resulting date is invalid (NaN), the server returned a getlastmodified value that isn't a parseable RFC1123 date, so the driver refuses to use a garbage timestamp for sync decisions.

Source

Thrown at packages/lib/file-api-driver-webdav.js:79

		}

		let lastModifiedString = null;

		try {
			lastModifiedString = this.api().resourcePropByName(resource, 'string', 'd:getlastmodified');
		} catch (error) {
			if (error.code === 'stringNotFound') {
				// OK - the logic to handle this is below
			} else {
				throw error;
			}
		}

		// Note: Not all WebDAV servers return a getlastmodified date (eg. Seafile, which doesn't return the
		// property for folders) so we can only throw an error if it's a file.
		if (!lastModifiedString && !isDir) throw new Error(`Could not get lastModified date for resource: ${JSON.stringify(resource)}`);
		const lastModifiedDate = lastModifiedString ? new Date(lastModifiedString) : new Date();
		if (isNaN(lastModifiedDate.getTime())) throw new Error(`Invalid date: ${lastModifiedString}`);

		return {
			path: path,
			updated_time: lastModifiedDate.getTime(),
			isDir: isDir,
		};
	}

	async setTimestamp() {
		throw new Error('Not implemented'); // Not needed anymore
	}

	async delta(path, options) {
		const getDirStats = async path => {
			const result = await this.list(path, { includeDirs: false });
			return result.items;
		};

View on GitHub (pinned to 2654b33620)

Solutions

  1. Inspect lastModifiedString in the message and normalize server-side to RFC1123 (e.g. configure Apache/nginx locale to C/en).
  2. If the server emits epoch or ISO, extend the parser to detect and convert those formats before new Date().
  3. Switch to a standards-compliant WebDAV server.
  4. As a last resort, patch the driver to fall back to current time and log a warning.

Example fix

// before
const lastModifiedDate = lastModifiedString ? new Date(lastModifiedString) : new Date();
if (isNaN(lastModifiedDate.getTime())) throw new Error(`Invalid date: ${lastModifiedString}`);
// after - try a couple of known formats, then degrade
const tryParse = (s) => {
  const d = new Date(s);
  if (!isNaN(d.getTime())) return d;
  const epoch = Number(s); return isNaN(epoch) ? null : new Date(epoch);
};
const lastModifiedDate = tryParse(lastModifiedString) ?? new Date();
if (!tryParse(lastModifiedString)) logger.warn('Unparsable WebDAV date:', lastModifiedString);
Defensive patterns

Strategy: fallback

Validate before calling

// Normalize the date string before relying on new Date().
function safeDate(s: string): Date | null {
  if (!s) return null;
  const d = new Date(s);
  if (!isNaN(d.getTime())) return d;
  const epoch = Number(s);
  return Number.isFinite(epoch) ? new Date(epoch) : null;
}

Type guard

function isParsableDate(s: string): boolean {
  if (!s) return false;
  if (!isNaN(new Date(s).getTime())) return true;
  return Number.isFinite(Number(s));
}

Try / catch

try {
  return await driver.stat(path);
} catch (e) {
  if (/Invalid date:/.test(e.message)) {
    logger.warn('WebDAV returned unparseable date; using current time for', path);
    return { path, updated_time: Date.now(), isDir: false };
  }
  throw e;
}

Prevention

When it happens

Trigger: stat()/list() on a WebDAV server whose getlastmodified value is malformed — e.g. a non-English locale date string, a numeric epoch, or a custom format the Date constructor can't parse.

Common situations: WebDAV server localized to a non-standard date format; server returning epoch numbers instead of RFC1123; proxy/gateway mangling header values; rare server bug emitting empty/garbage strings that survived the earlier non-empty check.

Related errors


AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12). Data as JSON: /api/errors/bae019e64ccb4714. Report an issue: GitHub.