{"record":{"id":"d883b268264bc91d","repo":"clockworklabs/SpacetimeDB","slug":"invalid-repository-format-use-owner-repo-or-ful","errorCode":null,"errorMessage":"Invalid repository format. Use 'owner/repo' or full git clone URL","messagePattern":"Invalid repository format\\. Use 'owner/repo' or full git clone URL","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/cli/src/subcommands/init.rs","lineNumber":999,"sourceCode":"        Some(value) if value.eq_ignore_ascii_case(\"csharp\") || value.eq_ignore_ascii_case(\"c#\") => \"C#\".to_string(),\n        Some(value) if value.eq_ignore_ascii_case(\"typescript\") => \"TypeScript\".to_string(),\n        Some(value) if value.eq_ignore_ascii_case(\"cpp\") || value.eq_ignore_ascii_case(\"c++\") => \"C++\".to_string(),\n        Some(value) if !value.trim().is_empty() => value.to_string(),\n        _ => \"None\".to_string(),\n    }\n}\n\nfn clone_github_template(repo_input: &str, target: &Path, is_server_only: bool) -> anyhow::Result<()> {\n    let is_git_url = |s: &str| {\n        s.starts_with(\"git@\") || s.starts_with(\"ssh://\") || s.starts_with(\"http://\") || s.starts_with(\"https://\")\n    };\n\n    let repo_url = if is_git_url(repo_input) {\n        repo_input.to_string()\n    } else if repo_input.contains('/') {\n        format!(\"https://github.com/{}\", repo_input)\n    } else {\n        anyhow::bail!(\"Invalid repository format. Use 'owner/repo' or full git clone URL\");\n    };\n\n    println!(\"  Cloning from {}...\", repo_url);\n\n    let temp_dir = tempfile::tempdir()?;\n\n    let mut builder = git2::build::RepoBuilder::new();\n\n    let mut fetch_options = git2::FetchOptions::new();\n    let mut callbacks = git2::RemoteCallbacks::new();\n\n    callbacks.credentials(|_url, username_from_url, allowed_types| {\n        if allowed_types.contains(git2::CredentialType::SSH_KEY)\n            && let Some(username) = username_from_url\n        {\n            return git2::Cred::ssh_key_from_agent(username);\n        }\n        if allowed_types.contains(git2::CredentialType::USER_PASS_PLAINTEXT) {","sourceCodeStart":981,"sourceCodeEnd":1017,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/cli/src/subcommands/init.rs#L981-L1017","documentation":"When a template reference is not a full git URL, init expects the `owner/repo` shorthand and expands it to `https://github.com/owner/repo`. Input that neither starts with `git@`/`ssh://`/`http://`/`https://` nor contains a slash is rejected before any clone is attempted. A bare repo name like `my-template` is the classic trigger.","triggerScenarios":"`spacetime init my-app --template my-template` (no owner, no slash); copy-paste that lost the owner part; passing a template id from the catalog where a git reference was expected.","commonSituations":"Assuming the template name alone identifies a repo; truncating URLs when copying; confusing catalog template ids with git shorthands.","solutions":["Use the shorthand with an owner: `--template clockworklabs/quickstart`","Or pass a full URL: `https://github.com/owner/repo`, or `git@github.com:owner/repo.git`","If you meant a builtin template, use its catalog id shown by `spacetime init --template=`"],"exampleFix":"# before\nspacetime init my-app --non-interactive --template quickstart-multiplayer\n\n# after — owner/repo shorthand\nspacetime init my-app --non-interactive --template clockworklabs/quickstart-multiplayer\n\n# after — full URL\nspacetime init my-app --non-interactive --template https://github.com/clockworklabs/quickstart-multiplayer","handlingStrategy":"validation","validationCode":"# Validate the template reference before init:\nref=\"$TEMPLATE\"\ncase \"$ref\" in\n  git@*|ssh://*|http://*|https://*) ;;           # full URL\n  */*) ref=\"https://github.com/$ref\" ;;          # owner/repo shorthand\n  *) echo \"invalid template ref '$ref' — use owner/repo or a full git URL\" >&2; exit 2 ;;\nesac\nspacetime init my-app --non-interactive --template \"$ref\"","typeGuard":"// Rust: accepts git/ssh/http(s) URLs or owner/repo shorthand.\nfn is_valid_repo_ref(s: &str) -> bool {\n    let s = s.trim();\n    s.starts_with(\"git@\")\n        || s.starts_with(\"ssh://\")\n        || s.starts_with(\"http://\")\n        || s.starts_with(\"https://\")\n        || s.split('/').count() == 2 && !s.is_empty()\n}","tryCatchPattern":"#!/usr/bin/env bash\nif ! spacetime init my-app --non-interactive --template \"$TEMPLATE\" 2>err.log; then\n  if grep -q \"Invalid repository format\" err.log; then\n    echo \"'$TEMPLATE' needs an owner: use owner/repo or a full URL\" >&2\n    exit 2\n  fi\n  cat err.log >&2; exit 1\nfi","preventionTips":["Always include the owner in shorthand references (owner/repo)","Quote template references in scripts so slashes and colons survive shell parsing","Note that 'github.com/owner/repo' without a protocol gets treated as shorthand and prefixed with https://github.com/ — prefer the canonical forms"],"tags":["init","template","git-url","validation"],"backgroundTag":"invalid-git-repository-reference","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}