MagicMirrorOrg/MagicMirror · warning

[compliments] Invalid URL: ${url}

Error message

[compliments] Invalid URL: ${url}

What it means

The compliments module logs this warning when the URL parsed in loadComplimentFile fails `new URL(url)` construction. The catch branch swallows the TypeError and warns, leaving `url` unset so the subsequent fetch is skipped or fetches an invalid target. It exists so a malformed remote compliment file URL degrades gracefully instead of crashing module startup.

Source

Thrown at defaultmodules/compliments/compliments.js:223

	/**
	 * Retrieve a file from the local filesystem
	 * @returns {Promise<string|null>} Resolved with file content or null on error
	 */
	async loadComplimentFile () {
		const { remoteFile, remoteFileRefreshInterval } = this.config;
		const isRemote = remoteFile.startsWith("http://") || remoteFile.startsWith("https://");
		let url = isRemote ? remoteFile : this.file(remoteFile);

		try {
			// Validate URL
			const urlObj = new URL(url);
			// Add cache-busting parameter to remote URLs to prevent cached responses
			if (isRemote && remoteFileRefreshInterval !== 0) {
				urlObj.searchParams.set("dummy", Date.now());
			}
			url = urlObj.toString();
		} catch {
			Log.warn(`[compliments] Invalid URL: ${url}`);
		}

		try {
			const response = await fetch(url);
			if (!response.ok) {
				Log.error(`[compliments] HTTP error: ${response.status} ${response.statusText}`);
				return null;
			}
			return await response.text();
		} catch (error) {
			Log.info("[compliments] fetch failed:", error.message);
			return null;
		}
	},

	/**
	 * Retrieve a random compliment.
	 * @returns {string} a compliment

View on GitHub (pinned to 4b4a59534f)

Solutions

  1. Fix the `remoteFile` value in the compliments config to a fully qualified absolute URL, e.g. 'https://example.com/compliments.json'.
  2. URL-encode or trim whitespace/invalid characters from the URL string.
  3. If the file is local, use the `complimentsFile` (local path) option instead of `remoteFile`.

Example fix

// before
config: { remoteFile: "example.com/compliments.json" }
// after
config: { remoteFile: "https://example.com/compliments.json" }
Defensive patterns

Strategy: validation

Validate before calling

function isValidRemoteFile(url) {
  try {
    const u = new URL(url);
    return u.protocol === "http:" || u.protocol === "https:";
  } catch {
    return false;
  }
}
// before use: if (!isValidRemoteFile(config.remoteFile)) console.warn("fix remoteFile");

Type guard

function isHttpUrl(value) {
  return typeof value === "string" && /^https?:\/\/\S+$/.test(value);
}

Prevention

When it happens

Trigger: Setting compliments config `remoteFile` to a string that is not an absolute valid URL (e.g. missing scheme, spaces, typos like 'htp://...' or 'example.com/file.json'); URL constructor throws and the catch logs this message before any fetch is attempted.

Common situations: Users copying a compliments config from docs and writing "remoteFile: 'birthday.json'" (relative path) instead of an absolute http(s) URL; trailing unencoded spaces or characters from copy-paste; protocol-relative '//example.com' strings in older configs.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of MagicMirrorOrg/MagicMirror@4b4a59534f (2026-08-31). Data as JSON: /api/errors/073de5d2fb7fe49c. Report an issue: GitHub.