gethomepage/homepage · error · Error
content must be a string
Error message
content must be a string
What it means
Thrown by write_config_file when the `content` argument is not a string. Homepage writes the value verbatim to the config file, so it must already be valid YAML/CSS/JS text — objects or other types are rejected before the write to avoid corrupting config.
Source
Thrown at src/utils/mcp/homepage-mcp.js:409
switch (name) {
case "list_config_files":
return textContent(JSON.stringify({ configDir: CONF_DIR, files: listConfigFiles() }, null, 2));
case "read_config_file": {
assertKnownConfigFile(args.file);
return textContent(readConfig(args.file));
}
case "validate_config_file": {
assertKnownConfigFile(args.file);
const content = Object.prototype.hasOwnProperty.call(args, "content") ? args.content : readConfig(args.file);
return textContent(JSON.stringify(validateYaml(args.file, content), null, 2));
}
case "write_config_file": {
const disabled = ensureWriteEnabled();
if (disabled) return disabled;
assertKnownConfigFile(args.file);
if (typeof args.content !== "string") {
throw new Error("content must be a string");
}
const validation = validateYaml(args.file, args.content);
if (!validation.valid) {
return {
isError: true,
...textContent(JSON.stringify(validation, null, 2)),
};
}
mkdirSync(CONF_DIR, { recursive: true });
writeFileSync(configPath(args.file), args.content, "utf8");
return textContent(
JSON.stringify({ written: args.file, bytes: Buffer.byteLength(args.content, "utf8") }, null, 2),
);
}
case "add_service":
return addService(args);
case "add_info_widget":
return addInfoWidget(args);View on GitHub (pinned to b6dca1ae03)
Solutions
- Pass content as a string containing valid YAML (or CSS/JS for custom files).
- If you have a JS object, stringify it with js-yaml's dump (or JSON.stringify for non-YAML) before calling.
- To validate without writing, use validate_config_file with the same string content first.
- Ensure HOMEPAGE_MCP_ALLOW_WRITE=true is set or the tool returns a 'writing disabled' result before this check.
Example fix
// before
{ "file": "services.yaml", "content": [{ Infra: [] }] }
// after
{ "file": "services.yaml", "content": "- Infra: []\n" } Defensive patterns
Strategy: type-guard
Validate before calling
function ensureContentString(content) {
if (typeof content !== 'string') {
throw new Error('content must be a string; serialize objects with js-yaml.dump or JSON.stringify');
}
return content;
} Type guard
function isContentString(v) {
return typeof v === 'string';
} Prevention
- Always stringify config payloads (YAML/CSS/JS text) before write_config_file.
- Validate with validate_config_file using the same string first.
- Confirm HOMEPAGE_MCP_ALLOW_WRITE=true before attempting writes.
- Keep a backup of the target file before programmatic writes.
When it happens
Trigger: write_config_file tool called with args.file valid but `typeof args.content !== 'string'`. Typical: caller sends a JSON object expecting the server to serialize it, sends a number/boolean, or omits content (and the field isn't handled by the optional branch above).
Common situations: MCP client serializes a config object instead of YAML-stringifying it; caller assumes the server accepts structured data; client omits content thinking the tool reads from elsewhere; templating engine emits a non-string.
Related errors
- Unsupported config file '${file}'. Supported files: ${CONFIG
- ${name} must be an object
- group must be a non-empty string
- name must be a non-empty string
- services.yaml must contain a top-level array
AI-assisted analysis of gethomepage/homepage@b6dca1ae03 (2026-08-13).
Data as JSON: /api/errors/f72cb454ae9dd438.
Report an issue: GitHub.