{"record":{"id":"cd569dd5d11d09dd","repo":"gethomepage/homepage","slug":"name-must-be-a-non-empty-string","errorCode":null,"errorMessage":"name must be a non-empty string","messagePattern":"name must be a non-empty string","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/utils/mcp/homepage-mcp.js","lineNumber":183,"sourceCode":"  return null;\n}\n\nfunction dumpYamlConfig(file, content) {\n  const dumped = yaml.dump(content, { lineWidth: -1, noRefs: true });\n  mkdirSync(CONF_DIR, { recursive: true });\n  writeFileSync(configPath(file), dumped, \"utf8\");\n  return dumped;\n}\n\nfunction addService(args) {\n  const disabled = ensureWriteEnabled();\n  if (disabled) return disabled;\n\n  if (typeof args.group !== \"string\" || !args.group.trim()) {\n    throw new Error(\"group must be a non-empty string\");\n  }\n  if (typeof args.name !== \"string\" || !args.name.trim()) {\n    throw new Error(\"name must be a non-empty string\");\n  }\n\n  const validation = validateYaml(\"services.yaml\", readConfig(\"services.yaml\"));\n  if (!validation.valid) {\n    return {\n      isError: true,\n      ...textContent(JSON.stringify(validation, null, 2)),\n    };\n  }\n\n  const services = parseYamlConfig(\"services.yaml\");\n  if (!Array.isArray(services)) {\n    throw new Error(\"services.yaml must contain a top-level array\");\n  }\n\n  const groupName = args.group.trim();\n  const serviceName = args.name.trim();\n  const serviceConfig = args.service ?? {};","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/gethomepage/homepage/blob/b6dca1ae033e613d8e692f9a161a3cc53a5a2857/src/utils/mcp/homepage-mcp.js#L165-L201","documentation":"Thrown by addService when the `name` argument is missing or not a non-empty string. The name becomes the service's display key inside its group, so an empty/missing name is rejected before touching YAML.","triggerScenarios":"add_service tool called with args.name undefined/null/non-string/empty/whitespace-only. Guard: `typeof args.name !== \"string\" || !args.name.trim()`.","commonSituations":"Client omits name thinking only the URL matters; sends an empty string; uses the URL as the name but forgets to populate the field; whitespace from a templated payload.","solutions":["Provide name as a non-empty trimmed string, e.g. \"Grafana\".","Use a distinct name within the target group — duplicates are caught later but a clear name avoids churn.","Verify the tool-call arguments include the `name` key.","Avoid array/object values for name."],"exampleFix":"// before\n{ \"group\": \"Monitoring\", \"service\": { \"href\": \"http://grafana:3000\" } }\n\n// after\n{ \"group\": \"Monitoring\", \"name\": \"Grafana\", \"service\": { \"href\": \"http://grafana:3000\" } }","handlingStrategy":"validation","validationCode":"function isNonEmptyString(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}\nif (!isNonEmptyString(args.name)) {\n  return { isError: true, message: 'name is required' };\n}","typeGuard":"function isNonEmptyString(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Treat name as required alongside group when calling add_service.","Validate before sending to get cleaner MCP error messages.","Avoid duplicate names within the same group.","Keep names short and human-readable."],"tags":["mcp","services","validation","configuration"],"backgroundTag":null,"analyzedSha":"b6dca1ae033e613d8e692f9a161a3cc53a5a2857","analyzedAt":"2026-08-13T04:48:44.121Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}