{"record":{"id":"a5a20ce30fd5b983","repo":"gethomepage/homepage","slug":"type-must-be-a-non-empty-string","errorCode":null,"errorMessage":"type must be a non-empty string","messagePattern":"type must be a non-empty string","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/utils/mcp/homepage-mcp.js","lineNumber":233,"sourceCode":"    return {\n      isError: true,\n      ...textContent(`Service '${serviceName}' already exists in group '${groupName}'.`),\n    };\n  }\n\n  group[groupName].push({ [serviceName]: serviceConfig });\n  const content = dumpYamlConfig(\"services.yaml\", services);\n  return textContent(\n    JSON.stringify({ written: \"services.yaml\", added: { group: groupName, service: serviceName }, content }, null, 2),\n  );\n}\n\nfunction addInfoWidget(args) {\n  const disabled = ensureWriteEnabled();\n  if (disabled) return disabled;\n\n  if (typeof args.type !== \"string\" || !args.type.trim()) {\n    throw new Error(\"type must be a non-empty string\");\n  }\n\n  const validation = validateYaml(\"widgets.yaml\", readConfig(\"widgets.yaml\"));\n  if (!validation.valid) {\n    return {\n      isError: true,\n      ...textContent(JSON.stringify(validation, null, 2)),\n    };\n  }\n\n  const widgets = parseYamlConfig(\"widgets.yaml\");\n  if (!Array.isArray(widgets)) {\n    throw new Error(\"widgets.yaml must contain a top-level array\");\n  }\n\n  const type = args.type.trim();\n  const options = args.options ?? {};\n  assertPlainObject(options, \"options\");","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/gethomepage/homepage/blob/b6dca1ae033e613d8e692f9a161a3cc53a5a2857/src/utils/mcp/homepage-mcp.js#L215-L251","documentation":"Thrown by addInfoWidget when the `type` argument is missing or not a non-empty string. Every entry in Homepage's widgets.yaml is keyed by widget type (e.g. resources, search, weather), so type is mandatory.","triggerScenarios":"add_info_widget tool called with args.type undefined/null/non-string/empty/whitespace. Guard: `typeof args.type !== \"string\" || !args.type.trim()`.","commonSituations":"Client omits type expecting it to default; sends the widget options under type; uses a numeric code; whitespace-only value from templating.","solutions":["Provide type as a non-empty string matching a supported Homepage info widget (e.g. \"resources\", \"search\", \"weather\", \"datetime\").","Consult the widgets.yaml docs (https://gethomepage.dev/configs/info-widgets/) for valid type names.","Verify the tool-call arguments object actually contains the `type` key.","Avoid trailing whitespace and quotes."],"exampleFix":"// before\n{ \"options\": { \"latitude\": 40.7 } }\n\n// after\n{ \"type\": \"weather\", \"options\": { \"latitude\": 40.7, \"longitude\": -74.0 } }","handlingStrategy":"validation","validationCode":"function isNonEmptyString(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}\nif (!isNonEmptyString(args.type)) {\n  return { isError: true, message: 'type is required' };\n}","typeGuard":"function isNonEmptyString(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Make type a required field in your MCP client schema for add_info_widget.","Reference the official widgets list for valid type names.","Trim and validate before sending.","Avoid placeholder values like 'unknown'."],"tags":["mcp","widgets","validation","configuration"],"backgroundTag":null,"analyzedSha":"b6dca1ae033e613d8e692f9a161a3cc53a5a2857","analyzedAt":"2026-08-13T04:48:44.121Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}