abhigyanpatwari/GitNexus · error · InvalidStoragePathError

must be an absolute, non-empty path.

Error message

${label} must be an absolute, non-empty path.

What it means

validateAbsolutePath is the strict validator for absolute storage configuration paths. It throws when the labeled value is empty or not a string, producing a message like '<label> must be an absolute, non-empty path.' It is used for resolved storage roots, ownership metadata, and root configuration, where a relative path is never acceptable.

Solutions

  1. Convert to an absolute path before the call: path.resolve(value) (relative paths resolve against cwd, which may not be what you want — prefer path.isAbsolute check).
  2. Fix the env/config value to a full absolute path (e.g. export GITNEXUS_STORAGE_PATH=/var/lib/gitnexus).
  3. Ensure the value is actually a string; JSON configs sometimes carry null/numbers where a path is expected.

Example fix

// before
configuredStoragePath(process.env.GITNEXUS_STORAGE_PATH ?? 'storage');
// after
const p = process.env.GITNEXUS_STORAGE_PATH ?? path.join(os.homedir(), '.gitnexus-storage');
if (!path.isAbsolute(p)) throw new Error(`Storage path must be absolute: ${p}`);
configuredStoragePath(p);
Defensive patterns

Strategy: validation

Validate before calling

if (typeof value !== 'string' || value.length === 0 || !path.isAbsolute(value)) {
  throw new Error(`${label} must be a non-empty absolute path (got: ${JSON.stringify(value)})`);
}

Type guard

const isAbsoluteNonEmptyPath = (v: unknown): v is string =>
  typeof v === 'string' && v.length > 0 && path.isAbsolute(v);

Try / catch

try {
  const p = resolved(value);
} catch (e) {
  if (e instanceof InvalidStoragePathError) throw new Error(`storage config invalid: ${e.message}`);
  throw e;
}

Prevention

When it happens

Trigger: Calling resolved(), root(), or readOwnershipMetadata() with an empty string or relative path for a value labeled 'Storage path'/'Storage root' etc., e.g. GITNEXUS_STORAGE_PATH set to 'repos' instead of '/data/repos'.

Common situations: Env var GITNEXUS_STORAGE_PATH / GITNEXUS_STORAGE_ROOT set to a relative path; config file with missing/blank absolute path field; programmatic use passing cwd-relative paths assuming they'd be resolved.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at gitnexus/src/storage/storage-resolver.ts:185

const filesystemErrorDetail = (error: unknown): string => {
  const code = (error as NodeJS.ErrnoException)?.code;
  return code ? `${code}: ${(error as Error)?.message ?? String(error)}` : String(error);
};

const resolveRepoPath = (value: string): string => {
  if (typeof value !== 'string' || value.length === 0) {
    throw new InvalidStoragePathError('Repository path must be non-empty.');
  }
  if (value.includes('\0')) {
    throw new InvalidStoragePathError('Repository path must not contain a NUL character.');
  }
  return path.resolve(value);
};

const validateAbsolutePath = (value: string, label: string): string => {
  if (typeof value !== 'string' || value.length === 0) {
    throw new InvalidStoragePathError(`${label} must be an absolute, non-empty path.`);
  }
  if (value.includes('\0')) {
    throw new InvalidStoragePathError(`${label} must not contain a NUL character.`);
  }
  if (!path.isAbsolute(value)) {
    throw new InvalidStoragePathError(`${label} must be an absolute path.`);
  }
  return path.resolve(value);
};

// Mirror registry lookup semantics without importing repo-manager and creating a cycle.
const canonicalRegistryPath = (value: string): string => {
  const resolved = path.resolve(value);
  try {
    return stripWindowsLongPathPrefix(fs.realpathSync.native(resolved));
  } catch {
    return stripWindowsLongPathPrefix(resolved);
  }

View on GitHub (pinned to ac9a4e9abd)