{"record":{"id":"e8b48254a9626b49","repo":"nexu-io/open-design","slug":"public-github-repository-metric-only-supports-rep","errorCode":null,"errorMessage":"public_github_repository_metric only supports /repos/{owner}/{repo} URLs","messagePattern":"public_github_repository_metric only supports /repos/(.+?)/(.+?) URLs","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/live-artifacts/refresh.ts","lineNumber":664,"sourceCode":"  });\n}\n\nfunction selectGithubRepositoryApiUrl(input: PublicGithubRepositoryMetricInput): URL {\n  const rawUrl = optionalString(input.url, 'input.url');\n  if (rawUrl === undefined) throw new Error('public_github_repository_metric requires input.url');\n\n  let url: URL;\n  try {\n    url = new URL(rawUrl);\n  } catch {\n    throw new Error('public_github_repository_metric input.url must be a valid URL');\n  }\n\n  if (url.protocol !== 'https:' || url.hostname !== 'api.github.com') {\n    throw new Error('public_github_repository_metric only supports https://api.github.com repository URLs');\n  }\n  if (!/^\\/repos\\/[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+$/.test(url.pathname)) {\n    throw new Error('public_github_repository_metric only supports /repos/{owner}/{repo} URLs');\n  }\n  url.search = '';\n  url.hash = '';\n  url.username = '';\n  url.password = '';\n  return url;\n}\n\nfunction selectGithubFields(input: PublicGithubRepositoryMetricInput): string[] {\n  if (input.fields === undefined) return ['stargazers_count', 'full_name', 'html_url', 'updated_at'];\n  if (!Array.isArray(input.fields)) throw new Error('input.fields must be an array of strings');\n  const fields = input.fields.filter((field): field is string => typeof field === 'string');\n  if (fields.length !== input.fields.length) throw new Error('input.fields must be an array of strings');\n  return fields.slice(0, 20);\n}\n\nasync function executePublicGithubRepositoryMetric(options: ExecuteLocalDaemonRefreshSourceOptions): Promise<BoundedJsonObject> {\n  const input = options.source.input as PublicGithubRepositoryMetricInput;","sourceCodeStart":646,"sourceCodeEnd":682,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/live-artifacts/refresh.ts#L646-L682","documentation":"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.","triggerScenarios":"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).","commonSituations":"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).","solutions":["Use exactly the form /repos/{owner}/{repo} with no trailing slash and no sub-resource path.","For sub-resources (issues, releases), do not use this tool; it is scoped to repository-level metrics only.","Verify owner/repo segments only contain allowed characters; rename or encode if necessary (encoding is not supported here)."],"exampleFix":"// before\ninput: { url: 'https://api.github.com/repos/octocat/Hello-World/issues' }\n// after\ninput: { url: 'https://api.github.com/repos/octocat/Hello-World' }","handlingStrategy":"validation","validationCode":"const REPO_PATH = /^\\/repos\\/[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+$/;\nfunction assertRepoPath(u: URL): void {\n  if (!REPO_PATH.test(u.pathname)) throw new Error('expected /repos/{owner}/{repo}');\n}","typeGuard":"function isRepoApiUrl(v: unknown): v is string {\n  if (typeof v !== 'string') return false;\n  try {\n    const u = new URL(v);\n    return u.protocol === 'https:' && u.hostname === 'api.github.com'\n      && /^\\/repos\\/[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+$/.test(u.pathname);\n  } catch { return false; }\n}","tryCatchPattern":null,"preventionTips":["Do not append sub-resources (issues, releases, comments) — the tool fetches repo-level data only.","Avoid trailing slashes; keep the path normalized.","When in doubt, build the URL from owner + repo strings rather than copying a URL."],"tags":["validation","path-routing","github-api","live-artifacts"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}