gethomepage/homepage · error · Error

${name} must be an object

Error message

${name} must be an object

What it means

Thrown by assertPlainObject() when a value the caller supplied (or that was read from YAML) is expected to be a plain object but is an array, primitive, null, or non-object. Used by addService/addInfoWidget/write helpers to keep YAML structure well-formed.

Source

Thrown at src/utils/mcp/homepage-mcp.js:154

      error: error.message,
      mark: error.mark
        ? {
            line: error.mark.line + 1,
            column: error.mark.column + 1,
            snippet: error.mark.snippet,
          }
        : undefined,
    };
  }
}

function isPlainObject(value) {
  return value && typeof value === "object" && !Array.isArray(value);
}

function assertPlainObject(value, name) {
  if (!isPlainObject(value)) {
    throw new Error(`${name} must be an object`);
  }
}

function ensureWriteEnabled() {
  if (!writeEnabled()) {
    return {
      isError: true,
      ...textContent("Writing is disabled. Set HOMEPAGE_MCP_ALLOW_WRITE=true to enable MCP config edits."),
    };
  }
  return null;
}

function dumpYamlConfig(file, content) {
  const dumped = yaml.dump(content, { lineWidth: -1, noRefs: true });
  mkdirSync(CONF_DIR, { recursive: true });
  writeFileSync(configPath(file), dumped, "utf8");
  return dumped;

View on GitHub (pinned to b6dca1ae03)

Solutions

  1. Pass a JSON object (not array, not string) for the indicated field — e.g. `"service": { "href": "..." }`.
  2. If the field is optional, omit it entirely so the `?? {}` default applies rather than sending null.
  3. Inspect the existing YAML file the tool is operating on — a malformed entry there can also trip this on read.
  4. Validate payload shape against the tool's input schema before sending.

Example fix

// before
{ "group": "Infra", "name": "Grafana", "service": ["http://grafana:3000"] }

// after
{ "group": "Infra", "name": "Grafana", "service": { "href": "http://grafana:3000", "description": "Dashboards" } }
Defensive patterns

Strategy: type-guard

Validate before calling

function isPlainObject(v) {
  return v != null && typeof v === 'object' && !Array.isArray(v);
}
// before add_service:
if (!isPlainObject(args.service)) args.service = {};

Type guard

function isPlainObject(v) {
  return v != null && typeof v === 'object' && !Array.isArray(v);
}

Prevention

When it happens

Trigger: assertPlainObject(value, name) called with a non-object. Concrete call sites: addService passes args.service (e.g. caller sent `"service": []` or `"service": "text"`); addInfoWidget passes args.options; both also pass the parsed `name` through. The check is `!isPlainObject(value)` where isPlainObject excludes arrays and null.

Common situations: MCP client sends a JSON array where an object was expected (service config as a list of strings); client omits the field and a default isn't supplied; an existing YAML file already has the wrong shape (e.g. a service entry is a string instead of a map).

Related errors


AI-assisted analysis of gethomepage/homepage@b6dca1ae03 (2026-08-13). Data as JSON: /api/errors/2575e29722b25861. Report an issue: GitHub.