nexu-io/open-design · error
public_github_repository_metric input.url must be a valid UR
Error message
public_github_repository_metric input.url must be a valid URL
What it means
Thrown by selectGithubRepositoryApiUrl when the input.url string cannot be parsed by the WHATWG URL constructor (new URL). This is the first validation gate for the public_github_repository_metric refresh source: the value must be a syntactically valid absolute URL before any host/path checks run. It exists because live-artifact refresh inputs are model-authored JSON, so untrusted/malformed strings must be rejected before any network call.
Source
Thrown at apps/daemon/src/live-artifacts/refresh.ts:657
return asBoundedRefreshOutput({
toolName: 'git.summary',
isRepository: true,
branch: branch.trim(),
status: compactExecOutput(status),
recentCommits: compactExecOutput(recentCommits),
diffStat: compactExecOutput(diffStat),
});
}
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');View on GitHub (pinned to 5be4028344)
Solutions
- Set input.url to a full absolute URL beginning with 'https://', e.g. 'https://api.github.com/repos/<owner>/<repo>'.
- If the value comes from a template substitution, verify the variable is bound and non-empty before refresh runs.
- Trim the string and reject empty before constructing the source so the error surfaces at authoring time, not refresh time.
Example fix
// before
input: { url: 'repos/octocat/Hello-World' }
// after
input: { url: 'https://api.github.com/repos/octocat/Hello-World' } Defensive patterns
Strategy: validation
Validate before calling
function assertGithubApiUrl(raw: unknown): URL {
if (typeof raw !== 'string' || raw.length === 0) throw new Error('input.url required');
let u: URL;
try { u = new URL(raw); } catch { throw new Error('input.url is not a valid URL'); }
return u;
}
// call before building the refresh source Type guard
function isUrlString(v: unknown): v is string {
if (typeof v !== 'string' || v.length === 0) return false;
try { new URL(v); return true; } catch { return false; }
} Prevention
- Author refresh sources through a builder that validates input.url with new URL() before emitting JSON.
- Strip whitespace and reject empty before constructing the source.
- Treat URL validation as an authoring-time concern, not just a runtime check.
When it happens
Trigger: A live artifact refresh source of type daemon_tool with toolName 'public_github_repository_metric' whose input.url is undefined-ish handled elsewhere but defined as empty string '', a relative path like 'repos/foo/bar', a malformed string like 'ht!tp://api.github.com', or any value new URL() rejects.
Common situations: Model emits input.url without a scheme (e.g. 'api.github.com/repos/...'); agent writes a GitHub web URL intending it as API URL but typos the scheme; JSON template used a placeholder like '${URL}' that was never substituted; trailing whitespace or invisible characters from a copied cell.
Related errors
- public_github_repository_metric only supports https://api.gi
- public_github_repository_metric only supports /repos/{owner}
- input.fields must be an array of strings
- connector refresh source requires connector metadata
- ${field} must be a dot-separated JSON path
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/ccd02f7da223ce65.
Report an issue: GitHub.