{"record":{"id":"6ef8c98b489925d0","repo":"abhigyanpatwari/GitNexus","slug":"refusing-to-register-resolved-metadata-storagepath-does-not","errorCode":null,"errorMessage":"Refusing to register ${resolved}: metadata storagePath does not match the selected storage directory.","messagePattern":"Refusing to register (.+?): metadata storagePath does not match the selected storage directory\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/storage/repo-manager.ts","lineNumber":1003,"sourceCode":"        `Refusing to register ${resolved}: metadata belongs to ${meta.repoPath}, not this repository.`,\n      );\n    }\n    if (\n      meta.storagePath === undefined &&\n      !registryPathEquals(\n        canonicalizePath(storagePath),\n        canonicalizePath(defaultStoragePath(resolved)),\n      )\n    ) {\n      throw new Error(\n        `Refusing to register ${resolved}: external storage metadata must bind storagePath to the selected directory.`,\n      );\n    }\n    if (\n      meta.storagePath !== undefined &&\n      !registryPathEquals(canonicalizePath(meta.storagePath), canonicalizePath(storagePath))\n    ) {\n      throw new Error(\n        `Refusing to register ${resolved}: metadata storagePath does not match the selected storage directory.`,\n      );\n    }\n  }\n\n  // Mutating writes must not treat an unreadable/truncated registry as empty\n  // (#3094): lenient `readRegistry()` returns `[]` on parse failure and would\n  // replace the machine-wide file with only this entry. ENOENT stays empty.\n  const entries = await readRegistryStrict();\n  const existingIdx = entries.findIndex((e) => {\n    // Canonicalise the STORED entry too so pre-canonicalisation\n    // registries (written by older versions, or paths passed in a\n    // different form) still match correctly. `canonicalizePath` falls\n    // back to `path.resolve` when the path no longer exists on disk,\n    // so stale entries that have been rm'd externally still resolve\n    // to a stable key instead of throwing.\n    const a = canonicalizePath(e.path);\n    const b = canonicalInput;","sourceCodeStart":985,"sourceCodeEnd":1021,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/ac9a4e9abd8fd3058c070b72c23402a4f887929a/gitnexus/src/storage/repo-manager.ts#L985-L1021","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Pass the same storagePath the metadata records (read it from the metadata file under the storage directory).","Re-run analyze so metadata is regenerated bound to the currently selected storagePath.","Update or delete the stale metadata file, then re-analyze and register.","Set GITNEXUS_STORAGE_PATH identically for both analyze and register runs."],"exampleFix":"// before\nawait registerRepo(repo, { storagePath: \"/old/slot\" }); // meta.storagePath: \"/new/slot\"\n// after\nawait registerRepo(repo, { storagePath: \"/new/slot\" });","handlingStrategy":"validation","validationCode":"const meta = JSON.parse(await readFile(path.join(storagePath, \"index-meta.json\"), \"utf8\"));\nif (meta.storagePath !== undefined && path.resolve(meta.storagePath) !== path.resolve(storagePath)) {\n  throw new Error(`meta.storagePath ${meta.storagePath} != selected ${storagePath}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await registerRepo(repoPath, { storagePath });\n} catch (err) {\n  if (/metadata storagePath does not match/.test(String(err))) {\n    // read meta.storagePath and pass that, or re-analyze, then retry\n  } else throw err;\n}","preventionTips":["Pass the storagePath exactly as recorded in the metadata receipt.","Re-analyze after moving or renaming external storage directories.","Avoid symlinks/relative paths when specifying storagePath; use canonical absolute paths.","Keep storage configuration consistent in CI between analyze and register steps."],"tags":["registry","storage-path","metadata","mismatch"],"backgroundTag":"conflicting-config-options","analyzedSha":"ac9a4e9abd8fd3058c070b72c23402a4f887929a","analyzedAt":"2026-09-15T23:29:44.066Z","contentChangedAt":"2026-09-15T23:29:44.066Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}