abhigyanpatwari/GitNexus · error · Error
Refusing to adopt branch metadata: storage is not owned by…
Error message
Refusing to adopt branch metadata: storage is not owned by this repository (${inspection.state}). What it means
When an explicit storagePath is provided for branch-metadata adoption, inspectStoragePath is run and must report state 'owned' — i.e. the directory's metadata identifies this repository as owner. Any other state (unowned, owned-by-another-repo, corrupt, empty) aborts the adoption, preventing a branch index from being attached to storage that belongs to someone else or has no valid ownership receipt.
Solutions
- Run `gitnexus analyze` with that storagePath for this repository first so the ownership metadata exists.
- Inspect the metadata file under the storage directory and correct the repoPath/ownership recorded there.
- Choose the storage directory this repository actually owns (default .gitnexus or its external slot).
- Ensure no two repositories share the same GITNEXUS_STORAGE_PATH slot.
Example fix
// before
await adoptBranch(repo, branch, { storagePath: "/shared/other-repo-slot" });
// after
await analyze({ repo, storagePath: "/repos/repo/.gitnexus" });
await adoptBranch(repo, branch, { storagePath: "/repos/repo/.gitnexus" }); Defensive patterns
Strategy: validation
Validate before calling
const meta = JSON.parse(await readFile(path.join(storagePath, "index-meta.json"), "utf8"));
if (path.resolve(meta.repoPath) !== path.resolve(repoPath)) {
throw new Error(`storage not owned by ${repoPath} (owned by ${meta.repoPath})`);
} Try / catch
try {
await adoptBranchMetadata(repo, branch, { storagePath });
} catch (err) {
if (/storage is not owned by this repository/.test(String(err)) && /\((.+)\)/.test(String(err))) {
const state = err.message.match(/\((.+)\)/)[1];
if (state === "unowned" || state === "missing") await analyze({ repo, storagePath });
} else throw err;
} Prevention
- Ensure the storage directory has this repo's ownership metadata (analyze there first).
- Never point two repositories at the same external storage slot.
- Verify storage directories weren't wiped/recreated before branch operations.
When it happens
Trigger: registerRepo branch adoption with resolvedStoragePath defined while inspectStoragePath(storagePath, resolved) returns a state other than 'owned' — e.g. the directory was never analyzed, its metadata names a different repo, or the metadata is missing/corrupt.
Common situations: Pointing branch adoption at an external directory another project owns; the external slot was wiped or its metadata deleted; two repos misconfigured with the same GITNEXUS_STORAGE_PATH slot.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- "branch" must be a string
- contains characters not allowed in a git ref
- entry does not identify a repo — name and storagePath must…
- must not be empty
- must not contain ".."
AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-09-15).
Data as JSON: /api/errors/ddc4c2d0b60353b3.
Report an issue: GitHub.
Appendix: source
Thrown at gitnexus/src/storage/repo-manager.ts:1261
const initialEntries = await readRegistry();
const initialIdx = isRegistered(initialEntries);
if (initialIdx < 0) return; // no-op, disk included (no self-heal)
const resolved = path.resolve(repoPath);
const storagePath =
resolvedStoragePath === undefined
? getStoragePaths(resolved).storagePath
: validateConfiguredStoragePath(resolvedStoragePath);
const registeredStoragePath = initialEntries[initialIdx].storagePath;
if (!registryPathEquals(canonicalizePath(registeredStoragePath), canonicalizePath(storagePath))) {
throw new Error(
`Refusing to adopt branch metadata: the registry storage path does not match the selected storage directory.`,
);
}
if (resolvedStoragePath !== undefined) {
const inspection = await inspectStoragePath(storagePath, resolved);
if (inspection.state !== 'owned') {
throw new Error(
`Refusing to adopt branch metadata: storage is not owned by this repository (${inspection.state}).`,
);
}
}
// Remove a shadowed sub-index directory, mirroring `clean --branch`'s
// containment guard: the target MUST live under .gitnexus/branches/.
const branchesRoot = path.join(storagePath, BRANCHES_DIR);
const branchDir = path.join(branchesRoot, branchSlug(branch));
const branchRelativePath = path.relative(branchesRoot, branchDir);
const branchDirIsContained =
branchRelativePath !== '' &&
branchRelativePath !== '..' &&
!branchRelativePath.startsWith(`..${path.sep}`) &&
!path.isAbsolute(branchRelativePath);
let dirGone = false;
if (branchDirIsContained) {
let rmError: NodeJS.ErrnoException | undefined;
await fs.rm(branchDir, { recursive: true, force: true }).catch((err: unknown) => {View on GitHub (pinned to ac9a4e9abd)