mastra-ai/mastra · error · Error

Invalid GitHub URL format

Error message

Invalid GitHub URL format

What it means

`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).

Source

Thrown at packages/cli/src/commands/create/create.ts:649

}

function looksLikeGitHubUrl(value: string): boolean {
  try {
    return new URL(value.startsWith('github.com/') ? `https://${value}` : value).hostname === 'github.com';
  } catch {
    return false;
  }
}

async function validateGitHubProject(githubUrl: string): Promise<{ isValid: boolean; errors: string[] }> {
  const errors: string[] = [];

  try {
    const urlParts = new URL(githubUrl).pathname.split('/').filter(Boolean);
    const owner = urlParts[0];
    const repo = urlParts[1]?.replace('.git', '');

    if (!owner || !repo) throw new Error('Invalid GitHub URL format');

    let packageJsonContent: string | null = null;
    let indexContent: string | null = null;

    for (const branch of ['main', 'master']) {
      try {
        const packageJsonResponse = await fetch(
          `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/package.json`,
        );
        if (!packageJsonResponse.ok) continue;

        packageJsonContent = await packageJsonResponse.text();
        const indexResponse = await fetch(
          `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/src/mastra/index.ts`,
        );
        if (indexResponse.ok) indexContent = await indexResponse.text();
        break;
      } catch {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Provide a full repository URL: `--template https://github.com/<owner>/<repo>`
  2. Append `.git` optionally — it is stripped automatically
  3. Strip query strings/fragments (`?tab=readme`, `#readme`) before passing
  4. If using a template slug instead, pass just the slug, not a partial URL

Example fix

// before
mastra create my-app --template https://github.com/mastra-ai
// after
mastra create my-app --template https://github.com/mastra-ai/template-agent-harness
Defensive patterns

Strategy: validation

Validate before calling

export function normalizeGitHubTemplateUrl(input: string): string {
  const url = new URL(input.startsWith('github.com/') ? `https://${input}` : input);
  if (url.hostname !== 'github.com' || url.protocol !== 'https:') {
    throw new Error(`Not a GitHub repository URL: ${input}`);
  }
  const parts = url.pathname.split('/').filter(Boolean);
  if (parts.length < 2) throw new Error(`GitHub URL must include owner and repo: ${input}`);
  return `https://github.com/${parts[0]}/${parts[1].replace(/\.git$/, '')}`;
}

Type guard

function isRepoUrl(value: string): boolean {
  try {
    const u = new URL(value);
    const parts = u.pathname.split('/').filter(Boolean);
    return u.hostname === 'github.com' && parts.length >= 2;
  } catch { return false; }
}

Try / catch

try {
  await create({ template: githubUrl });
} catch (error) {
  if (error instanceof Error && /Invalid GitHub URL|Invalid Mastra project/.test(error.message)) {
    console.error('Provide a full owner/repo GitHub URL');
  } else throw error;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/7409385939939146. Report an issue: GitHub.