nexu-io/open-design · error · Error

input.fields must be an array of strings

Error message

input.fields must be an array of strings

What it means

Thrown by selectGithubFields when input.fields is defined (not undefined) but is not an Array. The fields selector expects either an omitted field (defaults apply) or an array of strings; any other type (object, string, number, null) is rejected before filtering, because the subsequent length-comparison invariant assumes an array.

Source

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

    throw new Error('public_github_repository_metric input.url must be a valid URL');
  }

  if (url.protocol !== 'https:' || url.hostname !== 'api.github.com') {
    throw new Error('public_github_repository_metric only supports https://api.github.com repository URLs');
  }
  if (!/^\/repos\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(url.pathname)) {
    throw new Error('public_github_repository_metric only supports /repos/{owner}/{repo} URLs');
  }
  url.search = '';
  url.hash = '';
  url.username = '';
  url.password = '';
  return url;
}

function selectGithubFields(input: PublicGithubRepositoryMetricInput): string[] {
  if (input.fields === undefined) return ['stargazers_count', 'full_name', 'html_url', 'updated_at'];
  if (!Array.isArray(input.fields)) throw new Error('input.fields must be an array of strings');
  const fields = input.fields.filter((field): field is string => typeof field === 'string');
  if (fields.length !== input.fields.length) throw new Error('input.fields must be an array of strings');
  return fields.slice(0, 20);
}

async function executePublicGithubRepositoryMetric(options: ExecuteLocalDaemonRefreshSourceOptions): Promise<BoundedJsonObject> {
  const input = options.source.input as PublicGithubRepositoryMetricInput;
  const url = selectGithubRepositoryApiUrl(input);
  const fetchInit: RequestInit = {
    headers: {
      Accept: 'application/vnd.github+json',
      'User-Agent': 'open-design-live-artifact-refresh',
    },
  };
  if (options.signal !== undefined) fetchInit.signal = options.signal;
  const response = await fetch(url, fetchInit);
  if (!response.ok) {
    throw new Error(`public_github_repository_metric request failed with ${response.status}`);

View on GitHub (pinned to 5be4028344)

Solutions

  1. Pass input.fields as a JSON array of strings, e.g. ['stargazers_count', 'full_name'].
  2. If you want the defaults, omit input.fields entirely rather than passing null or ''.
  3. Validate at authoring time that Array.isArray(input.fields) before constructing the refresh source.

Example fix

// before
input: { url: '...', fields: 'stargazers_count,full_name' }
// after
input: { url: '...', fields: ['stargazers_count', 'full_name'] }
Defensive patterns

Strategy: type-guard

Validate before calling

function normalizeFields(f: unknown): string[] | undefined {
  if (f === undefined) return undefined;
  if (!Array.isArray(f)) throw new Error('input.fields must be a string array');
  return f as string[];
}

Type guard

function isStringArray(v: unknown): v is string[] {
  return Array.isArray(v) && v.every(x => typeof x === 'string');
}

Prevention

When it happens

Trigger: input.fields is a comma-separated string like 'stargazers_count,full_name'; input.fields is a single string 'stargazers_count'; input.fields is an object {0: '...'}; input.fields is null.

Common situations: Model writes fields as a string literal instead of a JSON array; template authoring tool serializes a list as a delimited string; copy-paste from a YAML doc loses array markers; misunderstanding the contract as accepting CSV.

Related errors


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