nexu-io/open-design · error · Error

public_github_repository_metric only supports /repos/{owner}

Error message

public_github_repository_metric only supports /repos/{owner}/{repo} URLs

What it means

Thrown by selectGithubRepositoryApiUrl when the URL host/scheme are correct but the pathname does not match /^\/repos\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/. The tool only fetches a single repository resource via the canonical /repos/{owner}/{repo} endpoint; deeper paths, query endpoints, or non-repository paths are rejected to keep the response shape bounded and predictable.

Source

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

  });
}

function selectGithubRepositoryApiUrl(input: PublicGithubRepositoryMetricInput): URL {
  const rawUrl = optionalString(input.url, 'input.url');
  if (rawUrl === undefined) throw new Error('public_github_repository_metric requires input.url');

  let url: URL;
  try {
    url = new URL(rawUrl);
  } catch {
    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;

View on GitHub (pinned to 5be4028344)

Solutions

  1. Use exactly the form /repos/{owner}/{repo} with no trailing slash and no sub-resource path.
  2. For sub-resources (issues, releases), do not use this tool; it is scoped to repository-level metrics only.
  3. Verify owner/repo segments only contain allowed characters; rename or encode if necessary (encoding is not supported here).

Example fix

// before
input: { url: 'https://api.github.com/repos/octocat/Hello-World/issues' }
// after
input: { url: 'https://api.github.com/repos/octocat/Hello-World' }
Defensive patterns

Strategy: validation

Validate before calling

const REPO_PATH = /^\/repos\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
function assertRepoPath(u: URL): void {
  if (!REPO_PATH.test(u.pathname)) throw new Error('expected /repos/{owner}/{repo}');
}

Type guard

function isRepoApiUrl(v: unknown): v is string {
  if (typeof v !== 'string') return false;
  try {
    const u = new URL(v);
    return u.protocol === 'https:' && u.hostname === 'api.github.com'
      && /^\/repos\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(u.pathname);
  } catch { return false; }
}

Prevention

When it happens

Trigger: Pathname is '/repos/octocat' (missing repo), '/repos/octocat/Hello-World/issues' (sub-resource), '/users/octocat' (wrong endpoint), '/repos/foo/bar/' (trailing slash), or contains disallowed characters in owner/repo segments (e.g. spaces, slashes).

Common situations: Model tries to fetch a specific issue or release endpoint by extending the path; developer appends query strings or fragments (these are stripped earlier but path depth still fails); owner or repo contains characters outside [A-Za-z0-9_.-] (rare but possible with renamed/special repos).

Related errors


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