{"record":{"id":"88c69444ae8e3e87","repo":"abhigyanpatwari/GitNexus","slug":"analysis-not-finalized-missing-registry-entry-for-resolved","errorCode":null,"errorMessage":"Analysis not finalized: missing registry-entry for ${resolved} at ${storagePath} (registry: ${getGlobalRegistryPath()})","messagePattern":"Analysis not finalized: missing registry-entry for (.+?) at (.+?) \\(registry: (.+?)\\)","errorType":"exception","errorClass":"AnalysisNotFinalizedError","httpStatus":null,"severity":"error","filePath":"gitnexus/src/storage/repo-manager.ts","lineNumber":1480,"sourceCode":"      ? getStoragePaths(resolved).storagePath\n      : validateConfiguredStoragePath(resolvedStoragePath);\n  const metaPath = path.join(storagePath, INDEX_METADATA_FILE);\n\n  try {\n    await fs.access(metaPath);\n  } catch {\n    throw new AnalysisNotFinalizedError(resolved, storagePath, 'meta', getGlobalRegistryPath());\n  }\n\n  const canonicalRepoPath = canonicalizePath(resolved);\n  const canonicalStoragePath = canonicalizePath(storagePath);\n  const registeredAtStoragePath = (await readRegistryStrict()).some(\n    (entry) =>\n      registryPathEquals(canonicalizePath(entry.path), canonicalRepoPath) &&\n      registryPathEquals(canonicalizePath(entry.storagePath), canonicalStoragePath),\n  );\n  if (!registeredAtStoragePath) {\n    throw new AnalysisNotFinalizedError(\n      resolved,\n      storagePath,\n      'registry-entry',\n      getGlobalRegistryPath(),\n    );\n  }\n};\n\n/**\n * Thrown by {@link assertSafeStoragePath} when {@link requireDeletableStoragePath}\n * rejects the registry entry. Repository-local `.gitnexus` may still be\n * removed when it is missing, empty, unowned, or foreign; an external slot\n * is removable only when metadata binds both the repository and that exact\n * path. CLI destructive commands (`remove`, `clean --all`) should catch this\n * and exit non-zero without deleting anything.\n */\nexport class UnsafeStoragePathError extends Error {\n  readonly kind = 'UnsafeStoragePathError' as const;","sourceCodeStart":1462,"sourceCodeEnd":1498,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/ac9a4e9abd8fd3058c070b72c23402a4f887929a/gitnexus/src/storage/repo-manager.ts#L1462-L1498","documentation":"AnalysisNotFinalizedError with kind 'registry-entry' means the metadata file exists at storagePath but readRegistryStrict found no registry entry pairing this repository path with this storagePath. Analysis is only considered finalized when both the on-disk metadata and a matching strict-read registry row exist.","triggerScenarios":"A finalize/read path finds meta at storagePath, but no entry in the global registry has entry.path == repo and entry.storagePath == storagePath (canonicalized comparison) — the metadata is present while the registry row is missing or points elsewhere.","commonSituations":"The registry file was manually edited, truncated, or restored from an older backup losing the row; the repo was analyzed with default storage but is now read with an explicit storagePath; registration failed midway after metadata write; environment (GITNEXUS_STORAGE_PATH) differs between analyze and read.","solutions":["Re-run `gitnexus analyze` with the same storage configuration so registration completes and the registry row is written.","Fix the registry file to include an entry pairing the repo path with this storagePath (or remove the orphan metadata and re-analyze).","Align GITNEXUS_STORAGE_PATH / storagePath option between the analyze and consuming commands.","Check the registry path in the message — you may be consulting a different registry than the one populated during analyze."],"exampleFix":"// before\nawait ensureFinalized(repo, { storagePath: \"/external/slot\" }); // no registry row\n// after\nawait registerRepo(repo, { storagePath: \"/external/slot\" });\nawait ensureFinalized(repo, { storagePath: \"/external/slot\" });","handlingStrategy":"validation","validationCode":"const entries = JSON.parse(await readFile(registryPath, \"utf8\"));\nconst ok = entries.some((e) =>\n  path.resolve(e.path) === path.resolve(repoPath) &&\n  path.resolve(e.storagePath) === path.resolve(storagePath));\nif (!ok) await registerRepo(repoPath, { storagePath });","typeGuard":null,"tryCatchPattern":"try {\n  await readIndex(repoPath, { storagePath });\n} catch (err) {\n  if (err instanceof AnalysisNotFinalizedError && err.kind === \"registry-entry\") {\n    await registerRepo(repoPath, { storagePath }); // write the missing row\n    await readIndex(repoPath, { storagePath });\n  } else throw err;\n}","preventionTips":["Complete the full analyze+register flow; don't abort midway.","Back up the registry file and validate it after restores.","Use identical storage configuration (env vars/options) for all commands on a repo.","If a metadata file exists but no row matches, re-analyze to resynchronize."],"tags":["registry","registration","storage-path","finalization"],"backgroundTag":"record-not-found","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"}