{"record":{"id":"073de5d2fb7fe49c","repo":"MagicMirrorOrg/MagicMirror","slug":"compliments-invalid-url-url","errorCode":null,"errorMessage":"[compliments] Invalid URL: ${url}","messagePattern":"\\[compliments\\] Invalid URL: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"defaultmodules/compliments/compliments.js","lineNumber":223,"sourceCode":"\t/**\n\t * Retrieve a file from the local filesystem\n\t * @returns {Promise<string|null>} Resolved with file content or null on error\n\t */\n\tasync loadComplimentFile () {\n\t\tconst { remoteFile, remoteFileRefreshInterval } = this.config;\n\t\tconst isRemote = remoteFile.startsWith(\"http://\") || remoteFile.startsWith(\"https://\");\n\t\tlet url = isRemote ? remoteFile : this.file(remoteFile);\n\n\t\ttry {\n\t\t\t// Validate URL\n\t\t\tconst urlObj = new URL(url);\n\t\t\t// Add cache-busting parameter to remote URLs to prevent cached responses\n\t\t\tif (isRemote && remoteFileRefreshInterval !== 0) {\n\t\t\t\turlObj.searchParams.set(\"dummy\", Date.now());\n\t\t\t}\n\t\t\turl = urlObj.toString();\n\t\t} catch {\n\t\t\tLog.warn(`[compliments] Invalid URL: ${url}`);\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await fetch(url);\n\t\t\tif (!response.ok) {\n\t\t\t\tLog.error(`[compliments] HTTP error: ${response.status} ${response.statusText}`);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn await response.text();\n\t\t} catch (error) {\n\t\t\tLog.info(\"[compliments] fetch failed:\", error.message);\n\t\t\treturn null;\n\t\t}\n\t},\n\n\t/**\n\t * Retrieve a random compliment.\n\t * @returns {string} a compliment","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/MagicMirrorOrg/MagicMirror/blob/4b4a59534f7da01e4030e46029fe9dd649a7675e/defaultmodules/compliments/compliments.js#L205-L241","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fix the `remoteFile` value in the compliments config to a fully qualified absolute URL, e.g. 'https://example.com/compliments.json'.","URL-encode or trim whitespace/invalid characters from the URL string.","If the file is local, use the `complimentsFile` (local path) option instead of `remoteFile`."],"exampleFix":"// before\nconfig: { remoteFile: \"example.com/compliments.json\" }\n// after\nconfig: { remoteFile: \"https://example.com/compliments.json\" }","handlingStrategy":"validation","validationCode":"function isValidRemoteFile(url) {\n  try {\n    const u = new URL(url);\n    return u.protocol === \"http:\" || u.protocol === \"https:\";\n  } catch {\n    return false;\n  }\n}\n// before use: if (!isValidRemoteFile(config.remoteFile)) console.warn(\"fix remoteFile\");","typeGuard":"function isHttpUrl(value) {\n  return typeof value === \"string\" && /^https?:\\/\\/\\S+$/.test(value);\n}","tryCatchPattern":null,"preventionTips":["Always use fully qualified http(s) URLs for remoteFile.","Trim and URL-encode config values copied from web pages.","Keep local files under the compliments module folder and use the local file option instead."],"tags":["url-parsing","config","network"],"backgroundTag":"invalid-url-format","analyzedSha":"4b4a59534f7da01e4030e46029fe9dd649a7675e","analyzedAt":"2026-08-31T21:49:42.591Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}