paperclipai/paperclip · error
Managed git install metadata is incomplete.
Error message
Managed git install metadata is incomplete.
What it means
Thrown by updateCommand when the install manifest's source is 'git' but one or more of repo, ref, or sha is missing/falsy. Git-sourced managed installs require all three fields to resolve the remote ref to a target commit and to detect when the ref is pinned (a hex ref). Without them the update flow cannot safely fetch or compare commits.
Source
Thrown at cli/src/commands/update.ts:185
export async function updateCommand(options: UpdateOptions, overrides: Partial<Dependencies> = {}): Promise<void> {
const paths = overrides.paths ?? resolveInstallStorePaths();
const executablePath = overrides.executablePath ?? process.argv[1] ?? "";
const runCommand = overrides.runCommand ?? execFileAsync;
const mode = detectInstallMode(executablePath, paths);
const manifest = readInstallManifest(paths);
if (options.rollback) {
if (mode !== "managed") throw new Error("--rollback is only available for managed installs.");
if (options.dryRun) { emit(options, { mode, action: "rollback", dryRun: true, target: manifest?.previous[0]?.version ?? null }, `Would roll back to ${manifest?.previous[0]?.version ?? "the previous payload"}.`); return; }
const next = await withInstallStoreLock(async () => rollbackManagedInstall(paths), paths);
const restarted = await (overrides.restartActiveService ?? restartActiveManagedService)(next.version);
emit(options, { mode, action: "rollback", version: next.version, restarted }, pc.green(`Rolled back to paperclipai ${next.version}${restarted ? " and restarted the active service" : ""}. Database migrations are not reversed; restore the pre-update backup if needed.`));
return;
}
if (mode === "npx") { emit(options, { mode, action: "install" }, "This is an ephemeral npx install. Run `paperclipai install`, then use `paperclipai update` from the managed shim."); return; }
if (mode === "source" || mode === "unknown") { emit(options, { mode, action: "manual" }, "This appears to be a source checkout. Update it with `git pull` followed by `pnpm install`; Paperclip will not mutate the repository."); return; }
const request = resolveUpdateRequest(mode === "managed" ? manifest : null, options);
if (mode === "managed" && manifest?.source === "git") {
if (!manifest.repo || !manifest.ref || !manifest.sha) throw new Error("Managed git install metadata is incomplete.");
if (/^[0-9a-f]{7,40}$/i.test(manifest.ref)) { emit(options, { mode, source: "git", pinned: true, sha: manifest.sha }, `Git install is pinned at ${manifest.sha.slice(0, 12)}.`); return; }
const targetSha = await resolveGitHubRef(manifest.repo, manifest.ref, runCommand);
if (targetSha === manifest.sha) { emit(options, { mode, source: "git", changed: false, sha: targetSha, ref: manifest.ref }, `${manifest.repo}@${manifest.ref} is already at ${targetSha.slice(0, 12)}.`); return; }
if (options.check || options.dryRun) { emit(options, { mode, source: "git", changed: true, currentSha: manifest.sha, targetSha, ref: manifest.ref, dryRun: Boolean(options.dryRun) }, `Git update available: ${manifest.sha.slice(0, 12)} → ${targetSha.slice(0, 12)}.`); if (options.check) process.exitCode = 10; return; }
if (options.yes !== true) {
const confirmed = await (overrides.confirm ?? defaultConfirm)(`Update from ${manifest.repo}@${manifest.ref} and execute build scripts from commit ${targetSha.slice(0, 12)}?`);
if (!confirmed) throw new Error("Git update cancelled. Re-run with --yes to confirm executing build scripts from the updated commit.");
}
if (options.backup !== false) await runPreUpdateBackup(options, overrides.backup ?? (() => dbBackupCommand({})), overrides.hasInstanceData);
const installed = await withInstallStoreLock(async () => {
const payload = await installGitPayload(manifest.repo!, targetSha, runCommand, paths);
const record: InstallRecord = { source: "git", version: payload.version, channel: "pinned", repo: manifest.repo, ref: manifest.ref, sha: targetSha, payloadPath: payload.payloadPath, installedAt: (overrides.now?.() ?? new Date()).toISOString() };
const next = buildNextManifest(record, manifest); const oldTarget = fs.readlinkSync(paths.currentPath); flipCurrentAtomic(payload.payloadPath, paths);
try { writeInstallManifestAtomic(next, paths); } catch (error) { flipCurrentAtomic(path.resolve(paths.cliRoot, oldTarget), paths); throw error; }
pruneInstallPayloads(next, paths); return payload;
}, paths);
let restarted: boolean;
try {View on GitHub (pinned to 67001ec6eb)
Solutions
- Reinstall the managed CLI from git with `paperclipai install --git <repo> --ref <ref>` to repopulate repo/ref/sha.
- Edit the manifest.json directly to fill in the missing repo, ref, and sha values if you know them.
- Fall back to an npm-channel install: `paperclipai install` (no --git) to switch off the git source.
Defensive patterns
Strategy: validation
Validate before calling
import { readInstallManifest, resolveInstallStorePaths } from '../install-store.js';
function gitManifestComplete(): boolean {
const m = readInstallManifest(resolveInstallStorePaths());
return Boolean(m && m.source === 'git' && m.repo && m.ref && m.sha);
}
// if (!gitManifestComplete()) { /* reinstall from git to repopulate fields */ } Type guard
function isCompleteGitManifest(m: unknown): m is { repo: string; ref: string; sha: string; source: 'git' } {
if (typeof m !== 'object' || m === null) return false;
const r = m as Record<string, unknown>;
return r.source === 'git' && typeof r.repo === 'string' && r.repo.length > 0
&& typeof r.ref === 'string' && r.ref.length > 0
&& typeof r.sha === 'string' && r.sha.length > 0;
} Prevention
- Do not hand-edit manifest.json — let the installer record all git fields.
- If migrating stores, copy manifest.json verbatim so repo/ref/sha survive.
- Re-run `paperclipai install --git <repo> --ref <ref>` to refresh metadata after any corruption.
When it happens
Trigger: Manifest source === 'git' and (manifest.repo, manifest.ref, or manifest.sha) is empty/null/undefined. Reached on the managed git branch of updateCommand (line 185). Can happen if the manifest was written by an older/buggy installer or hand-edited.
Common situations: Manifest corrupted or partially overwritten. Upgraded from an older CLI version that did not persist repo/ref/sha. Manual edits to manifest.json that dropped a field. Install recording interrupted mid-write.
Related errors
- Managed install metadata is missing.
- No managed install was found to roll back.
- No previous managed payload is available for rollback.
- Git update cancelled. Re-run with --yes to confirm executing
- The Paperclip database is not running or reachable, so the p
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/e45798b2de97249d.
Report an issue: GitHub.