abhigyanpatwari/GitNexus · error
Unsafe index storage path
Error message
Unsafe index storage path
What it means
This is the fallback message of the same 400 response: when requireDeletableStoragePath throws a non-StorageDeletionError, the handler returns err.message or the literal 'Unsafe index storage path'. It means the repository's storage path could not be validated as safe to delete for a reason not covered by the dedicated error type.
Solutions
- Verify the repo's storage directory exists on disk and is readable by the server process
- Check GITNEXUS_STORAGE_PATH / GITNEXUS_STORAGE_ROOT are set consistently with where the index lives
- Re-run `gitnexus analyze --index-only` in the repo to rebuild/re-register a valid storage layout
- Inspect the server logs for the underlying throw if err.message is empty
Example fix
// before: repo dir deleted, registry entry stale
rm -rf my-repo && curl -X DELETE localhost:4747/api/repos/my-repo
// 400 { error: 'Unsafe index storage path' }
// after: remove the stale entry cleanly
// restore or recreate the repo dir first, or edit the registry entry, then delete
curl -X DELETE localhost:4747/api/repos/my-repo // 200 Defensive patterns
Strategy: validation
Validate before calling
import { existsSync } from 'fs';
const ok = existsSync(storagePath) && existsSync(`${storagePath}/index`); // adjust to known layout
if (!ok) throw new Error('storage directory missing or unrecognized'); Try / catch
if (res.status === 400 && (await res.text()).includes('Unsafe index storage path')) {
// storage layout/registration problem — refresh the index instead of deleting
await exec('gitnexus analyze --index-only');
} Prevention
- Verify the repo entry's storagePath exists and is readable before issuing a delete
- Avoid custom GITNEXUS_STORAGE_* paths unless the same value is used by every client
- Check server permissions on the storage directory
When it happens
Trigger: DELETE /api/repos/:name where the storage-path validation throws an unexpected error — missing entry.path, filesystem errors stat-ing the directory, or a path that fails the safety check in requireDeletableStoragePath without producing a StorageDeletionError.
Common situations: Seen when the repo directory was removed from disk but the registry entry remains, permissions on the storage directory prevent stat, or a custom GITNEXUS_STORAGE_PATH points outside the allowed root.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- err.message
- Refusing to delete storage
- Refusing to delete storage: the storage inspection state is
- Refusing to delete storage: the target is the repository…
- Analysis not finalized: missing
AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-09-15).
Data as JSON: /api/errors/76d31f4b2a9e563f.
Report an issue: GitHub.
Appendix: source
Thrown at gitnexus/src/server/api.ts:1228
const repoName = requestedRepo(req);
if (!repoName) {
res.status(400).json({ error: 'Missing repo name' });
return;
}
const entry = await resolveRepo(repoName, false, undefined, { validateStorage: false });
if (!entry) {
res.status(404).json({ error: 'Repository not found' });
return;
}
let storagePath: string;
try {
storagePath = await requireDeletableStoragePath(entry);
} catch (err: any) {
if (err instanceof StorageDeletionError) {
res.status(400).json({ error: err.message });
return;
}
res.status(400).json({ error: err.message || 'Unsafe index storage path' });
return;
}
// Acquire repo lock — prevents deleting while analyze/embed is in flight
const lockKey = storagePath;
const lockErr = acquireRepoLock(lockKey);
if (lockErr) {
res.status(409).json({ error: lockErr });
return;
}
try {
// Close any open LadybugDB handle before deleting files
try {
await closeLbug();
} catch {}
// 1. Delete the .gitnexus index/storage directoryView on GitHub (pinned to ac9a4e9abd)