{"record":{"id":"7409385939939146","repo":"mastra-ai/mastra","slug":"invalid-github-url-format","errorCode":null,"errorMessage":"Invalid GitHub URL format","messagePattern":"Invalid GitHub URL format","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/create/create.ts","lineNumber":649,"sourceCode":"}\n\nfunction looksLikeGitHubUrl(value: string): boolean {\n  try {\n    return new URL(value.startsWith('github.com/') ? `https://${value}` : value).hostname === 'github.com';\n  } catch {\n    return false;\n  }\n}\n\nasync function validateGitHubProject(githubUrl: string): Promise<{ isValid: boolean; errors: string[] }> {\n  const errors: string[] = [];\n\n  try {\n    const urlParts = new URL(githubUrl).pathname.split('/').filter(Boolean);\n    const owner = urlParts[0];\n    const repo = urlParts[1]?.replace('.git', '');\n\n    if (!owner || !repo) throw new Error('Invalid GitHub URL format');\n\n    let packageJsonContent: string | null = null;\n    let indexContent: string | null = null;\n\n    for (const branch of ['main', 'master']) {\n      try {\n        const packageJsonResponse = await fetch(\n          `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/package.json`,\n        );\n        if (!packageJsonResponse.ok) continue;\n\n        packageJsonContent = await packageJsonResponse.text();\n        const indexResponse = await fetch(\n          `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/src/mastra/index.ts`,\n        );\n        if (indexResponse.ok) indexContent = await indexResponse.text();\n        break;\n      } catch {","sourceCodeStart":631,"sourceCodeEnd":667,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/cli/src/commands/create/create.ts#L631-L667","documentation":"`validateGitHubProject` in packages/cli/src/commands/create/create.ts:649 parses the given GitHub URL's pathname into owner/repo; if either segment is missing (e.g. a bare https://github.com or a single-segment path) it throws 'Invalid GitHub URL format', which is then surfaced as a validation failure ('Failed to validate GitHub repository: Invalid GitHub URL format'). The URL is only accepted when it contains exactly an owner and a repo (with optional .git suffix).","triggerScenarios":"Passing `--template https://github.com/mastra` (owner only), `--template https://github.com/`, or a malformed URL that survived parseGitHubRepositoryUrl's normalization but has <2 path segments.","commonSituations":"Copying a user/org profile URL instead of a repository URL; truncated URLs pasted into shells; URL-encoded paths or fragments altering segment counts; typos dropping the repo part.","solutions":["Provide a full repository URL: `--template https://github.com/<owner>/<repo>`","Append `.git` optionally — it is stripped automatically","Strip query strings/fragments (`?tab=readme`, `#readme`) before passing","If using a template slug instead, pass just the slug, not a partial URL"],"exampleFix":"// before\nmastra create my-app --template https://github.com/mastra-ai\n// after\nmastra create my-app --template https://github.com/mastra-ai/template-agent-harness","handlingStrategy":"validation","validationCode":"export function normalizeGitHubTemplateUrl(input: string): string {\n  const url = new URL(input.startsWith('github.com/') ? `https://${input}` : input);\n  if (url.hostname !== 'github.com' || url.protocol !== 'https:') {\n    throw new Error(`Not a GitHub repository URL: ${input}`);\n  }\n  const parts = url.pathname.split('/').filter(Boolean);\n  if (parts.length < 2) throw new Error(`GitHub URL must include owner and repo: ${input}`);\n  return `https://github.com/${parts[0]}/${parts[1].replace(/\\.git$/, '')}`;\n}","typeGuard":"function isRepoUrl(value: string): boolean {\n  try {\n    const u = new URL(value);\n    const parts = u.pathname.split('/').filter(Boolean);\n    return u.hostname === 'github.com' && parts.length >= 2;\n  } catch { return false; }\n}","tryCatchPattern":"try {\n  await create({ template: githubUrl });\n} catch (error) {\n  if (error instanceof Error && /Invalid GitHub URL|Invalid Mastra project/.test(error.message)) {\n    console.error('Provide a full owner/repo GitHub URL');\n  } else throw error;\n}","preventionTips":["Always pass full owner/repo URLs, not org or profile pages","Strip ?query and #fragment before passing template URLs","Validate with new URL() and count pathname segments (must be 2) before invoking"],"tags":["cli","github","url-validation","template"],"backgroundTag":"invalid-url-format","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}