{"record":{"id":"35f3224247d0c747","repo":"affaan-m/ECC","slug":"invalid-repo-format-repo-expected-owner-re","errorCode":null,"errorMessage":"Invalid repo format: \"${repo}\". Expected \"owner/repo\".","messagePattern":"Invalid repo format: \"(.+?)\"\\. Expected \"owner/repo\"\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/github-coordination/gh-api.js","lineNumber":8,"sourceCode":"'use strict';\n\nconst { spawnSync } = require('child_process');\n\nfunction normalizeRepo(repo) {\n  const parts = String(repo || '').split('/').filter(Boolean);\n  if (parts.length !== 2) {\n    throw new Error(`Invalid repo format: \"${repo}\". Expected \"owner/repo\".`);\n  }\n  const [owner, name] = parts;\n  return { owner, name };\n}\n\nfunction normalizeIssueNumber(value) {\n  const parsed = Number.parseInt(String(value), 10);\n  if (!Number.isFinite(parsed) || parsed <= 0) {\n    throw new Error(`Invalid issue number: ${value}`);\n  }\n  return parsed;\n}\n\nfunction normalizeLabelValue(label) {\n  if (typeof label === 'string') {\n    return label.trim();\n  }\n  if (label && typeof label === 'object') {","sourceCodeStart":1,"sourceCodeEnd":26,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/github-coordination/gh-api.js#L1-L26","documentation":"normalizeRepo converts a repository reference string into { owner, name } by splitting on '/' and requiring exactly two non-empty segments. Any input that doesn't yield exactly two parts — full URLs, 'owner/name/extra', empty strings, values without a slash, or non-string inputs coerced via String() — is rejected with this error naming the received value.","triggerScenarios":"Passing 'owner' (no slash), 'https://github.com/owner/name' (four parts), 'owner//name' (still fine after filtering, but 'a/b/c' fails), an empty string, or undefined/null (coerced to '') into normalizeRepo or any gh-api call that takes a repo.","commonSituations":"Passing a GitHub URL instead of the 'owner/name' shorthand; GITHUB_REPOSITORY missing so an empty string is used; repo names containing slashes for nested services mistakenly assumed supported; concatenating owner and name with the wrong separator.","solutions":["Pass the canonical 'owner/name' string form","Strip the URL prefix if you have a full URL: new URL(repo).pathname.replace(/^\\//, '') then validate","Resolve the repo from process.env.GITHUB_REPOSITORY when not explicitly provided","Pre-validate with a regex like /^[^/]+\\/[^/]+$/ before calling"],"exampleFix":"// before\nlistIssues('https://github.com/acme/widgets', ...) // 4 parts -> throws\n// after\nconst repo = process.env.GITHUB_REPOSITORY || 'acme/widgets'; // 'acme/widgets'\nlistIssues(repo, ...)","handlingStrategy":"validation","validationCode":"function parseRepo(repo) { const m = /^(?:https:\\/\\/github\\.com\\/)?([\\w.-]+)\\/([\\w.-]+)$/.exec(String(repo || '').replace(/\\.git$/, '')); if (!m) throw new Error(`bad repo: ${repo}`); return { owner: m[1], name: m[2] }; }","typeGuard":"const isOwnerName = (v) => typeof v === 'string' && /^[^/\\s]+\\/[^/\\s]+$/.test(v.trim());","tryCatchPattern":"try { listIssues(repo, opts); } catch (e) { if (String(e.message).includes('Invalid repo format')) console.error(`normalize '${e.message.match(/\"(.*)\"/)?.[1]}' to owner/name before calling`); throw e; }","preventionTips":["Always store and pass repos as 'owner/name', never full URLs","Resolve repo from GITHUB_REPOSITORY as a fallback in CI","Trim and validate the value at the entry point","Handle non-string inputs (null/undefined) before they reach normalizeRepo"],"tags":["github","format","argument"],"backgroundTag":"invalid-argument-format","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}