ruvnet/ruflo · error · Error

Key exceeds maximum nesting depth of

Error message

Key exceeds maximum nesting depth of ${MAX_NESTING_DEPTH}

What it means

Thrown by setNestedValue() in config-tools.ts:105, used by the config_set tool. Keys are dotted paths ('a.b.c'); after splitting on '.', a key with more than MAX_NESTING_DEPTH = 10 segments is rejected before any object mutation. This bounds recursion and keeps the config tree from being arbitrarily deepened by a single call.

Solutions

  1. Flatten the key to at most 10 segments: move the deepest levels into the value ('a.b.c.d': {remaining: 'nesting'})
  2. Set intermediate objects in two calls — write the deep subtree as a JSON value at a shallower key
  3. Serialize very deep structures to a JSON string value stored at a shallow key

Example fix

// before: 11 segments
await callTool('config_set', {
  key: 'integrations.github.webhooks.events.push.filters.branch.pattern',
  value: 'main',
}); // throws: Key exceeds maximum nesting depth of 10

// after: store the deep subtree as a value at a shallow key
await callTool('config_set', {
  key: 'integrations.github.webhooks',
  value: { events: { push: { filters: { branch: { pattern: 'main' } } } } },
});
Defensive patterns

Strategy: validation

Validate before calling

const MAX_DEPTH = 10;
function isAcceptableKey(key: string): boolean {
  const parts = key.split('.');
  return parts.length <= MAX_DEPTH && parts.every((p) => p && !['__proto__', 'constructor', 'prototype'].includes(p));
}
if (!isAcceptableKey(key)) throw new TypeError('config key too deep or contains a reserved segment');

Prevention

When it happens

Trigger: Calling config_set with a dotted key of 11+ segments, e.g. 'integrations.github.webhooks.events.push.filters.branch.pattern' — split('.') yields 11 parts and throws. The limit counts every segment including the final leaf key.

Common situations: Auto-generating keys from deep JSON paths or feature-flag hierarchies; mistaking a dotted hostname or semver string ('cdn.v2.example.com') for a shallow key; porting a deeply nested YAML config into flat dotted keys verbatim.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/f558213540c14252. Report an issue: GitHub.

Appendix: source

Thrown at v3/@claude-flow/cli/src/mcp-tools/config-tools.ts:105

}

const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);

function filterDangerousKeys(obj: Record<string, unknown>): Record<string, unknown> {
  const filtered: Record<string, unknown> = {};
  for (const [key, value] of Object.entries(obj)) {
    if (!DANGEROUS_KEYS.has(key)) {
      filtered[key] = value;
    }
  }
  return filtered;
}

function setNestedValue(obj: Record<string, unknown>, key: string, value: unknown): void {
  const MAX_NESTING_DEPTH = 10;
  const parts = key.split('.');
  if (parts.length > MAX_NESTING_DEPTH) {
    throw new Error(`Key exceeds maximum nesting depth of ${MAX_NESTING_DEPTH}`);
  }
  for (const part of parts) {
    if (DANGEROUS_KEYS.has(part)) {
      throw new Error(`Dangerous key segment rejected: ${part}`);
    }
  }
  let current = obj;
  for (let i = 0; i < parts.length - 1; i++) {
    const part = parts[i];
    if (!(part in current) || typeof current[part] !== 'object') {
      current[part] = {};
    }
    current = current[part] as Record<string, unknown>;
  }
  current[parts[parts.length - 1]] = value;
}

export const configTools: MCPTool[] = [

View on GitHub (pinned to fa13ee4ad6)