nexu-io/open-design · error

${firstIssue.path}: ${firstIssue.message}

Error message

${firstIssue.path}: ${firstIssue.message}

What it means

asBoundedRefreshOutput (refresh.ts:267-273) runs validateBoundedJsonObject(value, 'localRefreshOutput') on every refresh output before it is merged into the artifact dataJson. Bounded-JSON enforces structural caps (max depth, max string length, max array length, max object key count). If validation fails, the first issue's path and message are thrown so the caller knows exactly where the limit was exceeded.

Source

Thrown at apps/daemon/src/live-artifacts/refresh.ts:271

    throw toRefreshAbortError(error, run);
  } finally {
    clearTimeout(sourceTimeout);
    run.signal.removeEventListener('abort', onRunAbort);
  }
}

function isLocalDaemonRefreshToolName(value: string | undefined): value is LocalDaemonRefreshToolName {
  return value === 'project_files.search'
    || value === 'project_files.read_json'
    || value === 'git.summary'
    || value === 'public_github_repository_metric';
}

function asBoundedRefreshOutput(value: BoundedJsonObject): BoundedJsonObject {
  const result = validateBoundedJsonObject(value, 'localRefreshOutput');
  if (!result.ok) {
    const firstIssue = result.issues[0];
    throw new Error(firstIssue === undefined ? result.error : `${firstIssue.path}: ${firstIssue.message}`);
  }
  return result.value;
}

const SAFE_MAPPING_SEGMENT = /^[A-Za-z_][A-Za-z0-9_-]*$|^(?:0|[1-9][0-9]*)$/;
const UNSAFE_MAPPING_SEGMENTS = new Set(['__proto__', 'prototype', 'constructor']);

function parseMappingPath(path: string, field: string): string[] {
  const normalized = path.startsWith('$.') ? path.slice(2) : path;
  if (normalized.length === 0 || normalized.startsWith('.') || normalized.endsWith('.') || normalized.includes('..')) {
    throw new Error(`${field} must be a dot-separated JSON path`);
  }
  const segments = normalized.split('.');
  for (const segment of segments) {
    if (!SAFE_MAPPING_SEGMENT.test(segment) || UNSAFE_MAPPING_SEGMENTS.has(segment)) {
      throw new Error(`${field} contains unsupported JSON path segment: ${segment}`);
    }
  }

View on GitHub (pinned to 5be4028344)

Solutions

  1. Reduce the size or depth of the source output (smaller file, fewer commits, narrower connector query).
  2. For read_json, point input.path at a smaller slice of data or a pre-summarized file.
  3. Add an outputMapping.dataPaths to extract only the needed fields before they hit bounded-JSON validation.

Example fix

// before: refresh reads a deeply nested 2MB JSON file
// asBoundedRefreshOutput throws `$.deeply.nested.path: exceeds max depth`

// after: add outputMapping.dataPaths to keep only flat fields
const source = {
  type: 'daemon_tool',
  toolName: 'project_files.read_json',
  input: { path: 'data.json' },
  outputMapping: { dataPaths: [{ from: 'summary.total', to: 'summary.total' }] }
};
Defensive patterns

Strategy: validation

Validate before calling

import { validateBoundedJsonObject } from './schema.js'; // conceptually
function assertBoundedRefreshOutput(value: BoundedJsonObject): void {
  const r = validateBoundedJsonObject(value, 'localRefreshOutput');
  if (!r.ok) throw new Error(`${r.issues[0]?.path ?? '<root>'}: ${r.issues[0]?.message ?? r.error}`);
}
// call this on a sample output before wiring it as a refresh source

Type guard

function isBoundedRefreshOutput(value: unknown): boolean {
  const r = validateBoundedJsonObject(value as BoundedJsonObject, 'localRefreshOutput');
  return r.ok;
}

Try / catch

try {
  await refreshLiveArtifact(opts);
} catch (err) {
  if (err instanceof Error && /localRefreshOutput|exceeds/.test(err.message)) {
    // suggest reducing file size / adding outputMapping
  }
  throw err;
}

Prevention

When it happens

Trigger: A daemon_tool or connector refresh output (or a transformed/mapped output) violates a bounded-JSON constraint — e.g. an object nested too deeply, a string longer than the cap, or an array with too many entries.

Common situations: project_files.read_json on a very large or deeply nested JSON file; a git.summary whose recentCommits/diffStat arrays are large; a connector returning a huge payload; an outputMapping transform (compact_table/metric_summary) that still exceeds caps.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/779e20539e7448fc. Report an issue: GitHub.