abhigyanpatwari/GitNexus · error · Error

Refusing to register

Error message

Refusing to register ${resolved}: metadata storagePath does not match the selected storage directory.

What it means

registerRepo refuses registration when the metadata receipt's meta.storagePath does not match the storagePath option the caller selected. Production write paths must register the exact storage slot they validated; a mismatch means the metadata belongs to a different storage directory and the registry entry would be wrong.

Solutions

  1. Pass the same storagePath the metadata records (read it from the metadata file under the storage directory).
  2. Re-run analyze so metadata is regenerated bound to the currently selected storagePath.
  3. Update or delete the stale metadata file, then re-analyze and register.
  4. Set GITNEXUS_STORAGE_PATH identically for both analyze and register runs.

Example fix

// before
await registerRepo(repo, { storagePath: "/old/slot" }); // meta.storagePath: "/new/slot"
// after
await registerRepo(repo, { storagePath: "/new/slot" });
Defensive patterns

Strategy: validation

Validate before calling

const meta = JSON.parse(await readFile(path.join(storagePath, "index-meta.json"), "utf8"));
if (meta.storagePath !== undefined && path.resolve(meta.storagePath) !== path.resolve(storagePath)) {
  throw new Error(`meta.storagePath ${meta.storagePath} != selected ${storagePath}`);
}

Try / catch

try {
  await registerRepo(repoPath, { storagePath });
} catch (err) {
  if (/metadata storagePath does not match/.test(String(err))) {
    // read meta.storagePath and pass that, or re-analyze, then retry
  } else throw err;
}

Prevention

When it happens

Trigger: Calling registerRepo with opts.storagePath set while meta.storagePath exists but canonicalizes to a different directory (moved slot, renamed directory, symlink path differences resolved differently).

Common situations: The external storage directory was moved or renamed after analysis; a different GITNEXUS_STORAGE_PATH was exported in the registering shell than in the analyzing one; registering a copied repo whose metadata still points at the source repo's slot.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-09-15). Data as JSON: /api/errors/6ef8c98b489925d0. Report an issue: GitHub.

Appendix: source

Thrown at gitnexus/src/storage/repo-manager.ts:1003

        `Refusing to register ${resolved}: metadata belongs to ${meta.repoPath}, not this repository.`,
      );
    }
    if (
      meta.storagePath === undefined &&
      !registryPathEquals(
        canonicalizePath(storagePath),
        canonicalizePath(defaultStoragePath(resolved)),
      )
    ) {
      throw new Error(
        `Refusing to register ${resolved}: external storage metadata must bind storagePath to the selected directory.`,
      );
    }
    if (
      meta.storagePath !== undefined &&
      !registryPathEquals(canonicalizePath(meta.storagePath), canonicalizePath(storagePath))
    ) {
      throw new Error(
        `Refusing to register ${resolved}: metadata storagePath does not match the selected storage directory.`,
      );
    }
  }

  // Mutating writes must not treat an unreadable/truncated registry as empty
  // (#3094): lenient `readRegistry()` returns `[]` on parse failure and would
  // replace the machine-wide file with only this entry. ENOENT stays empty.
  const entries = await readRegistryStrict();
  const existingIdx = entries.findIndex((e) => {
    // Canonicalise the STORED entry too so pre-canonicalisation
    // registries (written by older versions, or paths passed in a
    // different form) still match correctly. `canonicalizePath` falls
    // back to `path.resolve` when the path no longer exists on disk,
    // so stale entries that have been rm'd externally still resolve
    // to a stable key instead of throwing.
    const a = canonicalizePath(e.path);
    const b = canonicalInput;

View on GitHub (pinned to ac9a4e9abd)