mastra-ai/mastra · error · MaterializeError
clone-failed
clone-failed
Error message
Refusing to materialize: invalid repo full name '${repo}'. What it means
Before building any git command, materializeRepo validates the repo full name against /^\w.-]+\/[\w.-]+$/ (owner/name). A value that fails the regex is rejected with this MaterializeError (code clone-failed) as defense in depth, so a malformed DB row can never inject shell or URL content into a clone command.
Source
Thrown at mastracode/factory/src/integrations/github/sandbox.ts:245
/**
* Materialize the repo inside the user's sandbox. Clones on first open, pulls on
* re-open. Always scrubs the install token from the remote afterwards and sets
* `materialized_at` on the per-user sandbox binding row.
*/
export async function materializeRepo(options: MaterializeRepoOptions): Promise<void> {
return timedPhase('workspace.materialize', () => materializeRepoImpl(options));
}
async function materializeRepoImpl(options: MaterializeRepoOptions): Promise<void> {
const { row: sandboxRow, repoInfo, sandbox, token, storage } = options;
const workdir = sandboxRow.sandboxWorkdir;
const repo = repoInfo.repoFullName;
// 0. Defense in depth: never build a git command from values that aren't
// strictly shaped, even if a malformed row reached the DB. Inputs are also
// validated at the route boundary before storage.
if (!/^[\w.-]+\/[\w.-]+$/.test(repo)) {
throw new MaterializeError(`Refusing to materialize: invalid repo full name '${repo}'.`, 'clone-failed');
}
if (!/^[A-Za-z0-9_./-]+$/.test(repoInfo.defaultBranch)) {
throw new MaterializeError(
`Refusing to materialize: invalid default branch '${repoInfo.defaultBranch}'.`,
'clone-failed',
);
}
// 1. Preflight: git must be installed in the sandbox template.
const gitVersion = await sh(sandbox, 'git --version');
if (gitVersion.exitCode !== 0) {
throw new MaterializeError(
'git is not installed in the sandbox. The sandbox template must include git.',
'git-missing',
);
}
const authUrl = tokenUrl(repo, token);View on GitHub (pinned to 75dd419e61)
Solutions
- Fix the stored repoFullName to the canonical 'owner/name' slug form and re-run materialization.
- Ensure route-boundary validation stores only owner/name (strip protocol/host before persisting).
- Re-sync the repository record from the GitHub API to repair malformed names.
Example fix
// before
repoInfo = { repoFullName: 'https://github.com/acme/widgets' };
// after
repoInfo = { repoFullName: 'acme/widgets' }; Defensive patterns
Strategy: validation
Validate before calling
const REPO_FULL_NAME = /^[\w.-]+\/[\w.-]+$/;
if (!REPO_FULL_NAME.test(repoFullName)) throw new Error(`invalid repo full name: ${repoFullName}`); Type guard
const isRepoFullName = (v: unknown): v is string => typeof v === 'string' && /^[\w.-]+\/[\w.-]+$/.test(v);
Try / catch
try {
await materializeRepo(options);
} catch (err) {
if (err instanceof MaterializeError && err.code === 'clone-failed' && err.message.includes('invalid repo full name')) {
// repair the stored record, then retry
await resyncRepository(options.repoInfo.id);
return materializeRepo(options);
}
throw err;
} Prevention
- Validate owner/name at every write boundary (API, sync jobs, migrations) before persisting.
- Never store full clone URLs in the repoFullName column; keep slug form only.
- Add a DB constraint or zod schema enforcing the owner/name shape.
- Seed dev databases via the normal sync path rather than hand-edited rows.
When it happens
Trigger: materializeRepo() called with repoInfo.repoFullName such as 'owner/', '/repo', 'owner name/repo', 'owner/repo#main', or a value with spaces, slashes beyond one, or URL characters — typically from a corrupted or hand-edited repository row.
Common situations: Local dev DB seeded by hand, a migration that stored full clone URLs instead of owner/name, or upstream data returning display names rather than slugs.
Related errors
- GitHub installation id is invalid.
- GitHub pull requests require an owner/repository source.
- A review comment requires commitId, path, line, and side unl
- A multi-line review comment requires both startLine and star
- GitHub triage comments require an owner/repository source.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/8fe0eda32297d830.
Report an issue: GitHub.