ruvnet/RuView · error · TypeError

guidance options must be an object

Error message

guidance options must be an object

What it means

getGuidance(input, options) requires the second argument, when supplied, to be a non-null, non-array object. The `= {}` default only covers undefined, so an explicitly passed null, array, or primitive throws 'guidance options must be an object' before topic/query validation.

Source

Thrown at harness/ruview/src/guidance.js:345

 *   topics: Array<{topic: string, summary: string}>,
 *   capabilities: Array<object>,
 *   entryPoints: string[],
 *   recommendedCommands: string[],
 *   relatedKnowledge: object[],
 *   sourceCheck: object,
 *   authority: string
 * }} Structured guidance suitable for CLI or MCP serialization.
 * @throws {TypeError|RangeError} When called directly with malformed input.
 *
 * @example
 * getGuidance({ topic: 'homecore', query: 'Wasmtime plugin' });
 */
export function getGuidance(input = {}, options = {}) {
  if (!input || typeof input !== 'object' || Array.isArray(input)) {
    throw new TypeError('guidance input must be an object');
  }
  if (!options || typeof options !== 'object' || Array.isArray(options)) {
    throw new TypeError('guidance options must be an object');
  }
  if (input.topic !== undefined && typeof input.topic !== 'string') {
    throw new TypeError('guidance topic must be a string');
  }
  if (input.query !== undefined && typeof input.query !== 'string') {
    throw new TypeError('guidance query must be a string');
  }
  if (input.limit !== undefined && (typeof input.limit !== 'number' || !Number.isFinite(input.limit))) {
    throw new TypeError('guidance limit must be a finite number');
  }
  if (options.repoRoot !== undefined && options.repoRoot !== null && typeof options.repoRoot !== 'string') {
    throw new TypeError('guidance repoRoot must be a string or null');
  }
  const topic = input.topic === undefined ? 'overview' : input.topic;
  if (!GUIDANCE_TOPICS.includes(topic)) {
    throw new RangeError(`unsupported guidance topic: ${topic}`);
  }
  const query = input.query === undefined ? '' : input.query.trim();

View on GitHub (pinned to 4685618388)

Solutions

  1. Omit the second argument entirely when there are no options: getGuidance({ topic: 'overview' }).
  2. Normalize before calling: options = (options === null || Array.isArray(options) || typeof options !== 'object') ? {} : options;
  3. If you previously passed a string repoRoot, migrate to getGuidance(input, { repoRoot }).

Example fix

// before
getGuidance({ topic: 'overview' }, null)
// after
getGuidance({ topic: 'overview' }) // or getGuidance({ topic: 'overview' }, {})
Defensive patterns

Strategy: type-guard

Validate before calling

const options = rawOptions === undefined || rawOptions === null ? {} : rawOptions;
if (typeof options !== 'object' || Array.isArray(options)) {
  throw new Error('guidance options must be an object');
}
getGuidance(input, options);

Type guard

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

Try / catch

try {
  getGuidance(input, options);
} catch (e) {
  if (e instanceof TypeError && e.message === 'guidance options must be an object') {
    return getGuidance(input, {});
  }
  throw e;
}

Prevention

When it happens

Trigger: getGuidance({}, null), getGuidance({ topic: 'overview' }, []), or a caller spreading a non-object collection into the options slot, e.g. getGuidance({}, ...extra) where extra is an array.

Common situations: Optional-argument threading where a caller passes null to mean 'no options'; forwarding MCP args arrays into the options position; refactors that changed options from a string (e.g. repoRoot) to an object.

Related errors


AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16). Data as JSON: /api/errors/3170c1dea050b62a. Report an issue: GitHub.