mastra-ai/mastra · error · MaterializeError
push-failed
push-failed
Error message
Refusing to push: invalid repo full name '${repoFullName}'. What it means
withInstallToken validates the repo full name against /^[\w.-]+\/[\w.-]+$/ before rewriting `origin` to a tokenized URL, throwing MaterializeError('push-failed') on mismatch. This guard prevents embedding an untrusted string into a remote URL (and later into a shell command), which could leak the install token or execute injection.
Source
Thrown at mastracode/factory/src/integrations/github/sandbox.ts:688
* **always** scrub the remote back to the tokenless URL afterwards. The token
* therefore only ever lives in the remote URL for the duration of the
* operation and is never left in the VM's git config.
*
* Once the tokenized URL is installed a failed scrub may leave the token
* persisted, so it is always surfaced: on its own after a successful `fn`,
* appended to `fn`'s own error otherwise — `fn`'s error is never replaced.
* Only a failed set-url (the token never reached the remote) downgrades the
* scrub to best-effort.
*/
export async function withInstallToken<T>(
sandbox: ExecutableSandbox,
workdir: string,
repoFullName: string,
token: string,
fn: () => Promise<T>,
): Promise<T> {
if (!/^[\w.-]+\/[\w.-]+$/.test(repoFullName)) {
throw new MaterializeError(`Refusing to push: invalid repo full name '${repoFullName}'.`, 'push-failed');
}
const setUrl = await sh(
sandbox,
`git -C ${shellQuote(workdir)} remote set-url origin ${shellQuote(tokenUrl(repoFullName, token))}`,
);
if (setUrl.exitCode !== 0) {
// Best-effort scrub even though set-url failed, then surface the failure.
await scrubRemote(sandbox, workdir, repoFullName, false);
throw new MaterializeError(`Failed to set git remote: ${setUrl.stderr.trim()}`, 'push-failed');
}
let result: T;
try {
result = await fn();
} catch (primary) {
throw await scrubbedFailure(sandbox, workdir, repoFullName, true, primary, 'push-failed');
}View on GitHub (pinned to 75dd419e61)
Solutions
- Normalize the repo full name to 'owner/repo' form before calling pushBranch
- Strip protocol/host if you have a full URL (extract the last two path segments)
- Trim whitespace and reject empty strings at the input boundary
Example fix
// before await pushBranch(sandbox, workdir, 'https://github.com/acme/widgets.git', branch, token); // after const repoFullName = 'acme/widgets'; await pushBranch(sandbox, workdir, repoFullName, branch, token);
Defensive patterns
Strategy: validation
Validate before calling
if (!/^[\w.-]+\/[\w.-]+$/.test(repoFullName)) {
throw new Error(`invalid repo full name: ${repoFullName}`);
} Type guard
function isValidRepoFullName(name: string): name is `${string}/${string}` {
return /^[\w.-]+\/[\w.-]+$/.test(name);
} Try / catch
try {
await pushBranch(sandbox, workdir, branch, token, repoFullName);
} catch (e) {
if (e instanceof MaterializeError && e.code === 'push-failed' && e.message.includes('invalid repo full name')) {
repoFullName = normalizeRepoFullName(repoFullName);
return pushBranch(sandbox, workdir, branch, token, repoFullName);
}
throw e;
} Prevention
- Store owner/repo as two separate fields and join at call time
- Extract repo name from URLs with a strict parser
- Never pass full clone URLs as repoFullName
When it happens
Trigger: Calling pushBranch with a repoFullName that is empty, contains spaces/slashes beyond the single owner/name separator, or shell metacharacters — e.g. a malformed value parsed from a git remote or an API payload.
Common situations: Parsing owner/name from a URL incorrectly (leaving 'https://github.com/' prefix), user-supplied repo names with typos, or passing a full clone URL instead of 'owner/repo'.
Related errors
- Cookie password must be at least 32 characters. Set OKTA_COO
- Cookie password must be at least 32 characters. Set WORKOS_C
- Invalid route path: "${path}". Path cannot contain '..', '?'
- Worker ${label} must stay within the deployed artifact root.
- pr-failed
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/7401b7019503796d.
Report an issue: GitHub.